简体   繁体   English

我们是否需要创建一个字段'volatile',如果 Thread1 进入同步块,更新它,仍然在同步块内,线程 2 在同步之外读取字段?

[英]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. * 编辑:我添加了“随后”以明确表示synchronizedvolatile都不足以确保线程将以某种特定顺序访问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.正确使用synchronizedvolatile只能确保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 可以在更新varrelease()信号量的许可,线程 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM