在java中同步"深入"?

Kev*_*lan 2 java synchronization object

让我们说你有:

public class Foo {
    public Bar b;
}
public class Bar {
    public int x;
    public int y;
}
Run Code Online (Sandbox Code Playgroud)

然后你打电话:

Foo f = new Foo();
....
synchronized(f) {
   f.b.x = 3;
   f.b.y = 5; //x and y must be adjacent primes at all times.
}
Run Code Online (Sandbox Code Playgroud)

如果我们的线程安全性很深?即同步(f)防止另一个线程(在它自己的同步(f)块内)在fb更新时看到fb?那么使用synchronized(this)呢?

SLa*_*aks 6

一点也不.

synchronized关键字仅影响大约在同一对象的其它的同步块.
它与对象本身无关.


Ale*_*x D 6

询问同步是否"深入"表明您还没有完全理解Java线程"同步"的工作原理.所有刚开始的Java程序员通常都有同样的误解 - "同步f使得访问f字段的线程安全".这是正确的.

当一个线程正在执行您的synchronized(f)块时,没有其他线程可以synchronized在同一对象上输入任何块或方法.就这些.

没有理由要f通过同步来保护可变字段f.您可以根据需要同步任何对象,只要您始终使用相同的对象,并且只要您在访问/修改字段时始终进行同步f.

相反,同步f并不意味着您对f字段的访问必然是线程安全的.你可以在程序的其他地方有一些其他的代码,修改f的字段没有任何同步,或者在不同的对象上同步.

如果这看起来令人困惑,那是因为它是.Java的设计者做出了错误的选择(将隐式互斥体与每个对象相关联),我们只需处理它.

  • @randomstring,从一开始就使用显式的互斥对象会更好,比如Ruby的`Mutex`类.这本来就不那么令人困惑了,Java实现不必在高锁定性能和低每个对象内存占用之间做出选择.如果需要,仍然可以使用"synchronized"方法 - 这些只是用于锁定/解锁私有字段中保存的"Mutex"对象的语法糖. (2认同)