1

我读到该synchronized方法或块提供了两个功能:“互斥”和“可见性”。我想知道两件事。

public class A{

  private final Object lock = new Object();
  private C obj = new C();

  public void methodA(){

      synchronized(lock){
        obj.x = 1;
        obj.y=3;
       }
    }

public void methodB(C obj2){

          synchronized(lock){
           obj2.x = obj.x;
           }


}

}

假设我们有 2 个线程调用methodA类型为 的全局共享对象A,并且 由lock获取thread1,现在在thread1释放lock. 现在可见性是所有其他线程将读取更改obj?即块内的每一个变化synchronized都是可见的吗?或者我应该更改 C 对象以volatile使其更改对其他人可见?

4

5 回答 5

2

Makingobj volatile引用C 对象volatile。即在同步块之外可见。它不会影响该对象的成员。

即对 obj 的重新分配将对另一个线程可见。不会对其成员进行重新分配。

于 2012-12-17T09:19:14.363 回答
1

同步块内的所有变化都是可见的吗?

是的,就是这样。JLS 17.45定义发生在关系之前。尤其是:

监视器上的解锁发生在该监视器上的每个后续锁定之前。

因此,当 thread2 获得锁时,您可以保证它会在持有相同锁的同时看到 thread1 所做的更改。

我应该将 C 对象更改为 volatile 以使其对其他人可见吗?

volatile 保证如果你在obj = new C();某处写: 后续读取obj将看到它现在指的是一个新对象。但是,它不提供关于 obj 的“内容”的任何此类保证。因此,如果您编写: obj.x = someValue;,并且 obj 是易失的,您不能保证更改将对另一个线程可见。除非你也变得x易变。

于 2012-12-17T09:19:21.393 回答
1

now the visibility is that all other thread will read the changes to obj ?

Only threads inside a synchronized block for that lock.

is every thing change inside the synchronized block will be visibile ?

Only probably. For guarenteed visibility the thread has to be inside a synchronized block.

or i should change C object to volatile ?

It will not help if you didn't have synchronized and will not make any difference here. volatile will only changes the behaviour of the obj reference, not it's fields.

于 2012-12-17T09:21:48.390 回答
0

No, accessing to obj fields is still not thread-safe. Synchronization on the lock object only allows you thread-safe operations for writing values to obj's fields in this block.

UPD: volatile for obj will not help you, because you don't change this field's own reference value.

于 2012-12-17T09:20:38.370 回答
0

要回答您的问题,另一种方法可以简单地让您访问变量 obj,而无需锁定。您必须确保对 obj 的所有访问都必须通过锁小心地保护,以便 obj 不会处于不一致的状态(如程序员所定义的那样)。

在您的特定示例中,它对我来说看起来足够一致。

于 2012-12-17T09:23:38.777 回答