我是担心竞争条件在应用我设计的,当我想知道关于这个问题。

让我们说有一大批或集合的某种管理的一个组成部分我的程序,让我们叫那个组件的监测。其工作是经常检查是否收集是"肮脏",i。e.已经改变,最近,如果是,写的快照磁盘(这是为了检查点的应用程序的情况下发生崩溃)和标记作为清洁。

其他组成部分的同一程序,运行不同的线,调监测的方法来增加数据或修改数据的阵/集合。这些方法标记的收集作为肮脏的。

现在,改变方法的运行中的其他成分'线,对吗?如果我不那么幸运,他们可能会被称为同时的快照是写入磁盘,变化数据已经编写,设置脏标记和监测取消设置的线,它只是在那之后,没有保存的变化(这已经是过去的元素,当它改变)。所以我有个肮脏的集的标记为清洁。

一段时间,我认为我也许可以解决的问题,通过制作一个临时的复制的收集、标记的清洁然后去和serialize的副本。但是,将复制原子能,i。e.我可以肯定,该收集将不会改变,而我复制吗?

与此同时,我想我已经找到更好的解决方案,喜欢

  • 设置一个锁标志开始之前写入磁盘,并使数据更改的方法等待,直到的标记被取消
  • 有数据修改的方法,写入一个"改变排队",而不是直接收集和有线,并盘书写过程中,排队

我认为锁定标志,可能是最好的路要走。 但我还是好奇:是复制的可变原子?


后续行动:也许这也应该去一个问题,但实际上这是非常相同。根据下面的答案,我的"锁定标志"的做法可能也不工作,对吗?因为数据修改的方法可能会检查锁定标志,虽然它被设定为"锁定"的价值,并决定这不是锁着的。所以我需要一个特殊的建筑就像一个互斥的,如果我真的想要这样做的权利,正确吗?


荣誉 埃里克森 对于他的 非常有益的答案 在我的后续行动。我真的应该让这两个问题,因此我可能已经接受两个答案。请表决,他太。

有帮助吗?

解决方案

没有。例如,只要的变量在Java不是原子32位的机器。

此外,还有一个"线的缓存"问题-除非你的变量是失的或内部同步块,另外一个线程可能不会看到改变的价值。这适用于所有类型的变量,而不只是漫长的。

在这里阅读: http://gee.cs.oswego.edu/dl/cpj/jmm.html, 尤其是"原子性"和"可见度"的段落。

其他提示

不,这不是原子的。 看到这个问题 为什么和怎样做它。

看看 java。工具.并行。原子 -可能有一些好东西在那里,你可以使用。

你需要关注的可见的变化的其他线上工作时JVM。在一般情况下,你应该让你的任内 synchronized 块,或变应该是 volatile, 或者你应该使用的变量包装从 java.util.concurrent.atomic 包。

然而,在你的情况下,这听起来就像你有一个线程,以往清除的"肮脏的"旗线,仍然存在的数据。如果是这种情况下,明确的标志 之前 写的数据。如果其他线设置它 同时 你写的数据,它将留置,直到下一个计划的编写。我用一个 AtomicBoolean, 来,给你的持久性线原子性之间的检查的标志和清除它,像这样:

private final AtomicBoolean dirty = new AtomicBoolean();

/**
 * Any method that modifies the data structure should set the dirty flag.
 */
public void modify() {
  /* Modify the data first. */
  ...
  /* Set the flag afterward. */
  dirty.set(true);
}

private class Persister extends Thread {
  public void run() {
    while (!Thread.interrupted()) {
      if (dirty.getAndSet(false)) {
        /* The dirty flag was set; this thread cleared it 
         * and should now persist the data. */
         ...
      }
    }
  }
}

设置一个32位(至少在。网)是原子,但它不会对你没有好处。你有读它知道,如果它是锁着的,所以你也许读它,然后读取别人读取之前可以设置,所以两个线程结束了 内部 "受保护"的代码。这正是什么样的实际步对象(。网络监类)。你可以使用一个相互联锁,检查和增量,锁定变量。

参见: 访问的一个变量在C#原子操作?

在很大程度上取决于硬件和JVM你正在运行

在某些硬件和一些Jvm一些副本将是原子 但它是更安全的假定不是这种情况甚至一个简单的整整数分配可以翻译为四个机器上的指示x856硬件。

串并列副本可以涉及一个序列中的成千上万的说明 和它可能对两个线程,以更新,同时.

我的理解是,并非总是如此。

Int32会,Int64不会在一个32位系统,因为它需要2x32位。因此,它不适合在一个32位的单元。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top