【问题标题】:Does volatile guarantee thread safety? This ArrayList examplevolatile 能保证线程安全吗?这个 ArrayList 示例
【发布时间】:2016-10-28 12:22:51
【问题描述】:

我有一个 ArrayList 'X',它被传递给多个线程,每个线程使用 addAll() 向这个 ArrayList 'X' 添加更多数据。显然这里存在多线程问题,一种选择是使代码的 addAll() 部分“同步”(或)使用 copyOnWriteArrayList。

但我的问题是,声明这个 ArrayList 'volatile' 会达到同样的目的吗? JVM 是否相应地对这些读/写指令进行排序并防止多线程问题?

【问题讨论】:

  • 不,volatile 不会同步访问,这就是 synchronized(或其他锁)的用途。
  • Volatile 在这里帮不了你。 volatile 指的是引用而不是列表的内容。您应该使用synchronized 锁定列表或让每个线程维护自己的列表(如果可能)并在处理完成时将列表组合在一起。
  • 我推荐阅读shipilev.net/blog/2016/close-encounters-of-jmm-kind/…(如果你有时间,可以阅读整篇文章)。
  • 这个问题提供了一些更有用的信息:stackoverflow.com/questions/9749746/…

标签: java multithreading arraylist volatile copyonwritearraylist


【解决方案1】:

声明这个 ArrayList 'volatile' 会达到同样的目的吗?

实际上你不能。当你写

volatile ArrayList list;

这使得list 引用易变,而不是底层的ArrayList。这也意味着当你这样做时

list.add(x);

list 已被读取,因此您只会获得读取屏障而不是写入屏障。

注意:这不会使操作成为原子操作,而这正是您真正需要的,但如果没有写屏障,您甚至可能在另一个线程中看不到此操作。

JVM 是否对这些读/写指令进行相应排序并防止多线程问题?

它将相应地对读取进行排序,但在这种情况下,它不会以一种可用于避免多线程问题的方式进行排序。也就是说,没有办法让这个工作与 volatile 一起工作,更不用说假设 JVM 会做你想做的事而不必担心。

synchronized通过比较可以正确使用。你仍然可能会出错,这不是万无一失的,但你很有可能会做对。

【讨论】:

    【解决方案2】:

    不,volatile 在这里不起作用。 Volatile 关键字只是确保每次读取操作始终获得最新的更新值。这里需要用到synchronized。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多