繁体   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?

假设我们有一个“A 类”,它有一个数据成员“var”。

class A
{
  int var;

method()
{
read(var);

synchronized block
{

update var here;

}

}

假设线程 1 获得锁并进入同步块。 它更新字段值“var”。 假设字段值由线程缓存在处理器的核心中。 它更新缓存中的值。

现在线程 2 开始运行,进入 method(),并读取字段值 'var'。

线程 2,肯定会得到更新的值吗? 是否同步确保线程 2 将获得更新的值,即使线程 1 尚未退出同步。 在这种情况下,我们是否需要使 'var' 易变?

PS - 一切都发生在同一个对象上。

是否同步确保线程 2 将获得更新的值

不,如果线程没有进入synchronized块, synchronized不会为线程做任何事情。 考虑synchronized的方法是这样的:无论一个线程在离开同步块之前做什么,都保证在第二个线程随后*进入在同一个锁对象上synchronized的块时对其他线程可见。

对于单个int变量,您可以改为将其volatile volatile提供类似于synchronized的保证:无论一个线程在更新volatile变量之前做什么,都保证在第二个线程随后*读取相同的volatile变量时对其他线程可见。


* 编辑:我添加了“随后”以明确表示synchronizedvolatile都不足以确保线程将以某种特定顺序访问var 如果您希望确保线程 2线程 1 分配它之前不会尝试读取var ,那么您将不得不使用其他一些方法†来协调它们的活动。 正确使用synchronizedvolatile只能确保IF线程 1 在线程 2 检查之前更新var ,然后线程 2 会看到更新。

† 有很多“其他方式”。 一个例子是Semaphore 线程 1 可以在更新varrelease()信号量的许可,线程 2 可以在读取var之前acquire()许可。 如果在线程 1 完成其工作之前到达信号量, acquire()调用将导致线程 2 等待。

如果你不让 'var' 易失,那么在写入和读取 'var' 之间就没有发生之前的边缘。 所以你手上有一个数据竞赛,奇怪的事情可能会发生,比如编译器把事情搞砸了。

简而言之:使其易失(或确保您使用相同的锁读取“var”)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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