多线程操作非线程安全 map 容器,读写里面的元素是否也需要加锁进行操作?
我一直有这样的疑问,比如有一个 Map<String, Student> map ;几个线程同时对这个 map 进行添加,删除,修改里面 Student 里的属性值,是不是这三种操作都需要锁住? 我很明确操作对这个 map 进行添加,删除,获取 size 都是需要锁住的,那么修改里面元素是不是也需要呢? 这个问题主要针对 C++和 Java 。
我一直有这样的疑问,比如有一个 Map<String, Student> map ;几个线程同时对这个 map 进行添加,删除,修改里面 Student 里的属性值,是不是这三种操作都需要锁住? 我很明确操作对这个 map 进行添加,删除,获取 size 都是需要锁住的,那么修改里面元素是不是也需要呢? 这个问题主要针对 C++和 Java 。
ps: 我突然想到 hashCode 的问题, 假设 Student 使用了 https://projectlombok.org/features/EqualsAndHashCode
,map=hashMap<Student, Object>
Student s1=new Student(“name”);
map.put(s1, “name”);
s1.name=”new”; // 会引起 hashCode 变化吧?
map.put(s1, “new”); // map.size 变成 2 了吧,哈哈哈
在 C++ 里,容器上的 const member function 是线程安全的。
然后在这里面 https://en.cppreference.com/w/cpp/container/map
const T& at( const Key& key ) const; 是线程安全的
T& operator[]( Key&& key ); 不是线程安全的,所以从 specification 的角度来说,有两个线程都在 m[key] 也是错的。
insert 当然不是线程安全的,明显不可能
必须所有线程上都只使用 const member function 才没有 data race,所以实际情况通常是这些操作全都要加锁。
Java 的 HashMap,https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html
If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.)
添加删除都需要加锁,修改一个已经存在的 entry 不需要。