13

我读了一些java代码,发现了这些函数:

synchronized void setConnected(boolean connected){
   this.connected = connected;
}

synchronized boolean isConnected(){
   return connected;
}

我想知道同步在这里是否有意义,或者只是作者不了解同步关键字的必要性?

我想同步在这里没用。还是我弄错了?

4

3 回答 3

19

关键字synchronized是确保线程安全的一种方式。当心:线程安全的(方式)比死锁​​更多,或者由于两个线程在没有同步的情况下递增一个 int 而丢失更新。

考虑以下类:

class Connection {
  private boolean connected; 
  synchronized void setConnected(boolean connected){
    this.connected = connected;
  }
  synchronized boolean isConnected(){
    return connected;
  }
}

如果多个线程共享一个实例Connection并且一个线程调用setConnected(true)synchronized那么其他线程就不可能一直看到isConnected() == false。该synchronized关键字保证所有线程都能看到该字段的当前值。

用更专业的术语来说,synchronized关键字确保了内存屏障(提示:google that)。

更详细地说:在释放监视器之前(即,在离开synchronized块之前)进行的每次写入都保证在获取相同监视器之后(即,在进入与同一对象同步的块之后)进行的每次读取都可以看到。在 Java 中,有一种叫做先发生(提示:google that)的东西,它不像“我按这个顺序编写代码,所以事情按这个顺序执行”那么简单。Usingsynchronized是一种建立前发生关系并保证线程看到内存的方法,就像你期望他们看到的那样。

在这种情况下,实现相同保证的另一种方法是消除synchronized关键字并标记字段volatile。提供的保证volatile如下:线程在 volatile 写入之前所做的所有写入都保证在后续对同一字段的 volatile 读取之后对线程可见。

最后一点,在这种特殊情况下,使用volatile字段而不是synchronized访问器可能会更好,因为这两种方法提供相同的保证,并且volatile-field 方法允许从不同线程同时访问该字段(如果synchronized版本争用太多)。

于 2013-04-05T07:24:13.160 回答
8

这里需要同步以防止内存一致性错误,请参阅http://docs.oracle.com/javase/tutorial/essential/concurrency/memconsist.html。尽管在这种具体情况下volatile将是更有效的解决方案

private volatile boolean connected;

void setConnected(boolean connected){
   this.connected = connected;
}

boolean isConnected(){
   return connected;
}
于 2013-04-05T07:28:54.407 回答
2

作者可能在设计代码时考虑了多线程方法。这意味着方法是同步的,并且多个线程将无法同时访问同一对象实例上的同步代码。

于 2013-04-05T07:25:03.483 回答