原始getter / setter方法需要java synchronized关键字? [英] java synchronized keyword needed on primitive getter / setter method?
问题描述
我读了一些java代码,发现了这些函数:
I read some java code, and found these functions:
synchronized void setConnected(boolean connected){
this.connected = connected;
}
synchronized boolean isConnected(){
return connected;
}
我想知道同步在这里是否有意义,或者只是作者不理解是否需要synchronized关键字?
I wonder if synchronization makes any sense here, or just author didn't understand the need for synchronized keyword?
我认为synchronized在这里没用。或者我错了?
I'd suppose that synchronized is useless here. Or am I mistaken?
推荐答案
关键字 synchronized
是一种方式确保线程安全。注意:线程安全比死锁更多,或因为两个线程在没有同步的情况下递增int而丢失更新。
The keyword synchronized
is one way of ensuring thread-safety. Beware: there's (way) more to thread-safety than deadlocks, or missing updates because of two threads incrementing an int without synchronization.
考虑以下类:
class Connection {
private boolean connected;
synchronized void setConnected(boolean connected){
this.connected = connected;
}
synchronized boolean isConnected(){
return connected;
}
}
如果多个线程共享一个<$ c $的实例c>连接并且一个线程调用 setConnected(true)
,没有 synchronized
这是可能的其他线程继续看到 isConnected()== false
。 synchronized
关键字保证所有线程都能看到该字段的当前值。
If multiple threads share an instance of Connection
and one thread calls setConnected(true)
, without synchronized
it is possible that other threads keep seeing isConnected() == false
. The synchronized
keyword guarantees that all threads sees the current value of the field.
在更多技术术语中,已同步
关键字可确保内存障碍(提示:google)。
In more technical terms, the synchronized
keyword ensures a memory barrier (hint: google that).
更多详情:在发布监视器之前进行的每次写入(即,在离开 synchronized
块之前)都保证在获取同一监视器后进行的每次读取都会看到(即,在进入阻止同一对象的同步)。在Java中,有一些名为发生在之前的事件(提示:google),这不像我按此顺序编写代码,因此事情按此顺序执行。使用 synchronized
是一种建立先发生关系的方法,并保证线程看到内存,就像你期望它们看到的一样。
In more details: every write made before releasing a monitor (ie, before leaving a synchronized
block) is guaranteed to be seen by every read made after acquiring the same monitor (ie, after entering a block synchronizing on the same object). In Java, there's something called happens-before (hint: google that), which is not as trivial as "I wrote the code in this order, so things get executed in this order". Using synchronized
is a way to establish a happens-before relationship and guarantee that threads see the memory as you would expect them to see.
在这种情况下,实现相同保证的另一种方法是消除 synchronized
关键字并标记字段 volatile
。 volatile
提供的保证如下所示:在对同一字段进行后续易失性读取之后,线程在易失性写入之前所做的所有写操作都保证对线程可见。
Another way to achieve the same guarantees, in this case, would be to eliminate the synchronized
keyword and mark the field volatile
. The guarantees provided by volatile
are as follows: all writes made by a thread before a volatile write are guaranteed to be visible to a thread after a subsequent volatile read of the same field.
作为最后一点,在这种特殊情况下,最好使用 volatile
字段而不是 synchronized
访问器,因为这两种方法提供相同的保证, volatile
-field方法允许从不同线程同时访问该字段(如果 synchronized
版本有太多争用,可能会提高性能。)
As a final note, in this particular case it might be better to use a volatile
field instead of synchronized
accessors, because the two approaches provide the same guarantees and the volatile
-field approach allows simultaneous accesses to the field from different threads (which might improve performance if the synchronized
version has too much contention).
这篇关于原始getter / setter方法需要java synchronized关键字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!