首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >同步跨线程共享但不并发访问的对象

同步跨线程共享但不并发访问的对象
EN

Stack Overflow用户
提问于 2012-10-11 11:45:03
回答 5查看 372关注 0票数 0

假设我有一个与字段data共享的对象。多个线程将共享对此对象的引用,以便访问该字段。但是,线程从不并发地访问对象。是否需要将data声明为易失性的?

这种情况如下:

  • Counter定义了唯一的字段value和一个方法increment
  • 一个线程增加计数器,然后生成另一个增加计数器的线程,等等。

考虑到程序本身的逻辑,无法并发访问计数器。然而,计数器是通过多个线程共享的。计数器必须是不稳定的吗?

这种情况的另一个变体是,多个线程通过依赖并发控制(waitnotifysynchronize)的另一个对象Y操作一个对象X,这个对象X是普通数据,但通过另一个依赖并发控制的对象Y交替执行它们的时间执行(这样X永远不会被并发访问)。对象X的字段应该是易失性的吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-10-14 06:51:21

只有在建立线程之间的关系之前,线程的突变才能在其他线程中可见。当建立起这种关系时,所有以前的突变都变得可见。

如果另一个对象正确地同步了对它的访问(请参见Java并发中的着色),隔离时未正确同步的对象可以安全地使用。

在问题中所述的两种情况下,我认为不需要同步:

  • Thread.start建立了一个发生之前的关系,因此以前线程中的所有突变都是可见的。
  • 对象Y对对象X的访问是同步的,这将在关系发生之前建立起来,并使对X的更改可见(我在博客文章中做了更多的扩展)。

如果您知道对象X从未被并发访问,那么很可能有一个对象Y间接地同步了对X的访问,所以它很好。我所看到的唯一不安全的情况是线程本身是否按时间中继(例如,使用Thread.sleep或循环直到某个时间中断)以保证互斥:在建立关系之前,在这种情况下不会发生。

票数 0
EN

Stack Overflow用户

发布于 2012-10-11 11:55:30

研究整个JLS关于Java内存模型的章节是非常推荐的--事实上,对于任何在Java中执行并发性的人来说都是强制性的。您的案例,特别是在JLS,17.4.4:中涵盖了。

“启动线程的动作与它启动的线程中的第一个动作同步。”

这意味着,对于第一个场景,您不需要volatile。但是,无论如何,让它对代码的未来更改保持健壮是很好的做法。您应该有一个很好的理由让(而不是)拥有volatile,只有在读取速率非常高(至少每秒数百万)的情况下才会有volatile

票数 3
EN

Stack Overflow用户

发布于 2012-10-11 11:47:40

Java内存模型和字节码重新排序并不保证后续线程将看到计数器的增量值。因此,如果您使用单个线程--您不需要对挥发物做任何事情,但是如果有几个线程可能从变量中读取某些内容--您需要确保对另一个线程的更改的可见性,无论是易失性线程还是同步/锁线程。

Thread.start方法设置了屏障,因此可见性得到了保证--而且可能会发生这样的情况:您不需要那些易挥发的东西。但我还是会加进去的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12838776

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档