为什么说“不可变对象无需同步”呢?
Topic source个人理解,廖老师的例子可能不是很恰当。
“不可变对象”通常是指创建之后状态一定不会再发生改变的对象(它里面的引用是final,引用的对象是不可变对象,而且没有setter等方法)。例如
class MyClass {
final String str;
MyClass(String str) {this.str = str;}
String getStr() {return str;}
}
那么这个Myclass类的对象就是“不可变对象”。显然,这样的对象一经创建就固定下来了,只能读不能写,用户类当然可以随意使用,不需要再做同步。
但是在下面廖老师的例子中,
class Data { List<String> names; void set(String[] names) { this.names = List.of(names); } List<String> get() { return this.names; } }
Data类并不是不可变的。虽然这里实例变量names所引用的对象是不可变的(由set方法保证),但是names这个引用是可变的。之所以这个类的set和get无需同步,与其说是因为“names所指向的对象是不可变的”,不如说是因为this.names = ...;和return this.names;都是原子操作。只要这里不只有names一个变量要set和get,它就不是线程安全的了。
当然,即便一个类不是不可变的,如果它的变量所引用的对象都是不可变的,还是可以减轻多线程编程的负担,因为这样就只需要保证“写引用、读引用及其对象”这两种操作是线程安全的就行了。你的例子之所以不是线程安全的,就是因为write和read方法没有对str这个引用的读写做同步。在线程A执行read时,如果线程B插进来要写str,此时A进行了几次读取是不确定的,B写完之后A再读,就会出问题。为了实现线程安全,就要做同步,保证read的一系列读操作不会被别的线程打断就可以了。
- 1
Sefank
比如说下面这个例子,str虽然是不可变的String,但不给write()加锁还是会出现read()三次读取的字符不是来自同一个字符串吧?