[英]Do we need to make a field 'volatile', if Thread1 enters sync block, updates it, is still inside the sync block, Thread2 outside of sync reads field?
Let's say we have 'class A' which has a data member 'var'.假设我们有一个“A 类”,它有一个数据成员“var”。
class A
{
int var;
method()
{
read(var);
synchronized block
{
update var here;
}
}
Let's say Thread 1 acquires the lock and enters the synchronized block.假设线程 1 获得锁并进入同步块。 It updates the field value 'var'.它更新字段值“var”。 Let's say the field value is cached in the processor's core by the Thread.假设字段值由线程缓存在处理器的核心中。 It updates the value in the cache.它更新缓存中的值。
Now thread 2 starts running, enters method(), and reads field value 'var'.现在线程 2 开始运行,进入 method(),并读取字段值 'var'。
Wil thread 2, surely get the updated value?线程 2,肯定会得到更新的值吗? Does synchronize makes sure thread 2 will get updated value even when Thread 1 has not exited Synchronized.是否同步确保线程 2 将获得更新的值,即使线程 1 尚未退出同步。 In this case, do we need to make 'var' volatile?在这种情况下,我们是否需要使 'var' 易变?
PS - Everything is happening on the same object. PS - 一切都发生在同一个对象上。
Does synchronize makes sure thread 2 will get updated value是否同步确保线程 2 将获得更新的值
No. synchronized
doesn't do anything for a thread if the thread does not enter a synchronized
block.不,如果线程没有进入synchronized
块, synchronized
不会为线程做任何事情。 The way to think about synchronized
is this: Whatever one thread does before it leaves a synchronized block is guaranteed to become visible to some other thread by the time the second thread subsequently* enters a block that is synchronized
on the same lock object.考虑synchronized
的方法是这样的:无论一个线程在离开同步块之前做什么,都保证在第二个线程随后*进入在同一个锁对象上synchronized
的块时对其他线程可见。
For a single int
variable, you could make it volatile
instead.对于单个int
变量,您可以改为将其volatile
。 volatile
makes a guarantee similar to the guarantee of synchronized
: Whatever one thread does before it updates a volatile
variable is guaranteed to become visible to some other thread by the time the second thread subsequently* reads the same volatile
variable. volatile
提供类似于synchronized
的保证:无论一个线程在更新volatile
变量之前做什么,都保证在第二个线程随后*读取相同的volatile
变量时对其他线程可见。
* Edit: I added "subsequently" to make it clear that neither synchronized
nor volatile
is sufficient to ensure that the threads will access var
in some particular order. * 编辑:我添加了“随后”以明确表示synchronized
和volatile
都不足以确保线程将以某种特定顺序访问var
。 If you wish to ensure that thread 2 will not try to read var
until after thread 1 has assigned it, then you will have to use some other means† to coordinate their activity.如果您希望确保线程 2在线程 1 分配它之前不会尝试读取var
,那么您将不得不使用其他一些方法†来协调它们的活动。 Correct use of synchronized
or volatile
only can ensure that IF thread 1 updates var
before thread 2 examines it, then thread 2 will see the update.正确使用synchronized
或volatile
只能确保IF线程 1 在线程 2 检查之前更新var
,然后线程 2 会看到更新。
† There are many "other means." † 有很多“其他方式”。 One example is a Semaphore
.一个例子是Semaphore
。 Thread 1 could release()
a permit to the semaphore after it updates var
, and thread 2 could acquire()
the permit before it reads var
.线程 1 可以在更新var
后release()
信号量的许可,线程 2 可以在读取var
之前acquire()
许可。 The acquire()
call would cause thread 2 to wait if it arrived at the semaphore before thread 1 had done its job.如果在线程 1 完成其工作之前到达信号量, acquire()
调用将导致线程 2 等待。
If you would not make 'var' volatile, then there is no happens-before edge between writing and reading 'var'.如果你不让 'var' 易失,那么在写入和读取 'var' 之间就没有发生之前的边缘。 So you have a data race on your hands and weird things can happen like the compiler messing things up.所以你手上有一个数据竞赛,奇怪的事情可能会发生,比如编译器把事情搞砸了。
So in short: make it volatile (or make sure you read 'var' using the same lock).简而言之:使其易失(或确保您使用相同的锁读取“var”)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.