【发布时间】:2018-10-29 15:57:17
【问题描述】:
我有一个用例,其中多个线程可以读取和修改 ArrayList,其中这些布尔值的默认值为 True。
线程可以进行的唯一修改是将 ArrayList 的一个元素从 True 设置为 False。
所有线程也会同时读取 ArrayList,但可以读取过期值。
注意: ArrayList 的大小在 ArrayList 的整个生命周期内都不会改变。
问题:
是否有必要在这些线程之间同步 ArrayList?我正在做的唯一同步是将 ArrayList 标记为易失性,这样对它的任何更新都会从线程的本地内存刷新回主内存。这够了吗?
这是一个关于线程如何使用这个 ArrayList 的示例代码
myList 是有问题的 ArrayList,其值被初始化为 True
if (!myList.get(index)) {
return;
} else {
// do some operations to determine if we should
// update the value of myList to False.
if (needToUpdateList) {
myList.set(index, False);
}
}
更新
我之前说过这些线程不关心过时的值,这是真的。但是,我有另一个线程只读取这些值并执行一个最终操作。该线程确实关心陈旧性。同步要求有变化吗?
除了每次更新都需要同步之外,还有更便宜的方法来“发布”更新的值吗?我正在尝试尽可能减少锁定。
【问题讨论】:
-
Volatile 确保 变量 的可见性,而不是变量持有的对象。因此,如果您初始化此列表一次,并尝试使用 volatile 来保证元素的可见性,那么它并没有按照您的想法进行
-
您介意详细说明一下“因此,如果您要初始化此列表一次,那么 volatile 将根本无法帮助您”
-
当然。听起来您从未更改过变量(即
myList = someNewList)。 volatile 的唯一帮助是确保每个线程上的myList指向正确的东西。因为您没有重新分配变量(我猜),所以它是多余的 -
关于“初始化”的更多信息:它是 Java 多线程模式的一部分。
volatile使该字段可见,并且还使所有先前的操作可见(不是迈克尔所说的那样)。但它对后续操作没有任何作用。参考文献Brian Goetz 的 Java Concurrency in Practice 和这个相关问题:stackoverflow.com/questions/801993/… -
请发布 List
的特定索引如何更新的代码。例如,如果代码将索引设置为空,然后将其设置为新的布尔值,那么除非到处都有空检查,否则这将不是线程安全的。
标签: java multithreading arraylist