我读了一些java代码,发现了这些函数:
synchronized void setConnected(boolean connected){
this.connected = connected;
}
synchronized boolean isConnected(){
return connected;
}
我想知道同步在这里是否有意义,或者只是作者不了解同步关键字的必要性?
我想同步在这里没用。还是我弄错了?
我读了一些java代码,发现了这些函数:
synchronized void setConnected(boolean connected){
this.connected = connected;
}
synchronized boolean isConnected(){
return connected;
}
我想知道同步在这里是否有意义,或者只是作者不了解同步关键字的必要性?
我想同步在这里没用。还是我弄错了?
关键字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
版本争用太多)。
这里需要同步以防止内存一致性错误,请参阅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;
}
作者可能在设计代码时考虑了多线程方法。这意味着方法是同步的,并且多个线程将无法同时访问同一对象实例上的同步代码。