在java竞争条件下最糟糕的情况是什么?

时间:2017-08-02 23:35:52

标签: java multithreading race-condition atomicity

我知道这显然是一种竞争条件。但是可能发生的事情是什么?

class Blah {
    List<String> stuff;
    public List<String> getStuff() {
        return stuff
    }
    public void setStuff(List<String> newValue) {
        this.stuff = newValue
    }
}

b = new Blah();
// Thread one
b.setStuff(getListFromSomeNetworkResource());
for (String c : b.getStuff()) {
  // Work with c
}


// Thread two
b.setStuff(getListFromSomeNetworkResource());
for (String c : b.getStuff()) {
  // Work with c
}
  1. 这可以抛出RuntimeException吗?
  2. 这个段错误jvm?
  3. 这个段错误可以吗?
  4. 是否依赖于处理器。如果它是Intel Xeon处理器怎么办?
  5. 这可以抛出NullPointer异常吗?
  6. 如果函数实际返回不同的值
  7. ,则线程2可以读取线程1设置的内容,反之亦然

    我知道这是竞争条件,不会写这样的代码。但是,我如何说服别人不要?

    更新

    假设:

    1. getListFromSomeNetworkResource()始终返回新的ArrayList。大小可以是0或更多。
    2. getListFromSomeNetworkResource()是线程安全的。

2 个答案:

答案 0 :(得分:0)

  

这会抛出RuntimeException吗?

不,如果 getListFromSomeNetworkResource()是线程安全的,并且不会返回null

  

这个段错误jvm?

     

这个段错误可以吗?

     

是否依赖于处理器。如果它是Intel Xeon处理器怎么办?

没有

  

这会抛出NullPointer异常吗?

仅当getListFromSomeNetworkResource()可以返回null时。

  

如果函数实际返回不同的值

,则线程2可以读取线程1设置的内容,反之亦然
是的,这可能会发生。

答案 1 :(得分:-1)

危险将是如下的排序:

  1. 主题一:b.setStuff(getListFromSomeNetworkResource());
  2. 线程二:b.setStuff(getListFromSomeNetworkResource());
  3. 主题一:b.stuff.iterator()(通过b.getStuff(),在 循环的开头)
  4. 在这种情况下,线程1 可以迭代线程二集的列表。从第二个线程到第一个线程的那个发布没有任何同步就完成了 - 这是一个数据竞争。假设列表本身不是线程安全的,可能会发生很多事情。主要问题是由于数据竞争,一些列表的状态对于第一个而不是全部可见。

    • 它可能会抛出一些RuntimeException。例如,由于调整大小,可能一个字段认为列表具有n个元素。但是来自调整大小的新数组没有完成,所以最终得到了一个ArrayIndexOutOfBoundsException
    • 由于各种原因,它可能会抛出NullPointerException;也许它是一个链表,其中一个参考写入没有使它成为一个

    它不应该导致任何段错误:那些只能来自JVM中的错误,但从不会在代码中出现错误。

    它可能取决于处理器,因为处理器可能有不同的处理方式,例如将内存从一个CPU缓存刷新到另一个CPU缓存 - 这是不安全发布可能导致您只看到一些数据的原因之一thread写道,来自另一个线程。有办法强迫这些缓存刷新;在Java中指定它们的方法是通过各种数据同步机制(获取锁,使用volatile字段等)。