当前位置:  开发笔记 > 编程语言 > 正文

在多线程(Java或.Net)程序中,我可以假设复制变量是原子的吗?

如何解决《在多线程(Java或.Net)程序中,我可以假设复制变量是原子的吗?》经验,为你挑选了2个好方法。

当我想知道这个问题时,我在设计的应用程序中担心竞争条件.

假设我有一个大型数组或某种类型的集合,由我的程序的一个组件管理,让我们称之为组件Monitor.它的工作是定期检查集合是否"脏",即最近是否已更改,如果是,则将快照写入磁盘(这是为了在发生崩溃时检查应用程序)并再次将其标记为干净.

在不同线程中运行的同一程序的其他组件调用Monitor的方法来向数组/集合中添加数据或修改数据.这些方法将集合标记为脏.

现在,改变方法在其他组件的线程中运行,对吧?如果我不是那么幸运,可以在快照写入磁盘时调用它们,更改已经写入的数据,设置脏标志,监视器的线程在此之后取消设置,而不保存更改(它当它改变时已经超过了元素).所以我有一个标记为干净的脏集合.

有一段时间,我认为我可以通过制作集合的临时副本来解决问题,将其标记为干净,然后再序列化副本.但复制是否是原子的,即我可以确定在复制时集合不会改变吗?

与此同时,我认为我找到了更好的解决方案

在开始写入磁盘之前设置锁定标志,并使数据更改方法等待,直到取消设置该标志

让数据更改方法写入"更改队列"而不是直接写入集合,并让具有磁盘写入进程的线程队列

我认为锁定标志可能是最好的方式.但我仍然好奇:复制变量原子?


后续行动:也许这应该是一个自己的问题,但实际上它是非常相同的.根据下面的答案,我的"锁定旗帜"方法可能也行不通,对吧?因为数据更改方法可能会在将锁定标志设置为"锁定"值时检查锁定标志并确定它未锁定.所以我需要一个像mutex这样的特殊结构,如果我真的想做到这一点,对吗?


荣誉对埃里克森对他非常有帮助的答案在我的跟进.我真的应该提出这两个问题,所以我可以接受两个答案.拜托,也请他投票.



1> Yoni Roit..:

不可以.例如,Java中的长变量在32位机器上不是原子的.

此外,还存在"线程缓存"问题 - 除非您的变量是易失性或在同步块内,否则另一个线程可能看不到变量值的变化.对于所有类型的变量都是如此,而不仅仅是长期变量.

请阅读此处:http://gee.cs.oswego.edu/dl/cpj/jmm.html,尤其是"原子性"和"可见性"段落.



2> Jason Cohen..:

不,这不是原子的. 请参阅此问题,了解为何以及如何处理该问题.

推荐阅读
依然-狠幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有