【问题标题】:Maintain reference then assign new object thread safe?维护引用然后分配新对象线程安全吗?
【发布时间】:2019-04-05 00:53:27
【问题描述】:
我有一个在线程之间共享的静态 int 数组:
static int[] res = new int[10];
在一个函数中,我想隔离 res 中的内容,基本上,将其值重置为 0。以下代码是线程安全的吗?
final int[] copy = res;
res = new int[10];
// do sth with `copy`
如果不是,在不损害性能的情况下,有什么更聪明的方法(除了使用 AtomicInteger 或 Semaphore)。
【问题讨论】:
标签:
java
multithreading
concurrency
【解决方案1】:
它不是线程安全的。无法保证其他线程何时会看到静态变量 res 的更改。
你可以改成:
static volatile int[] res = new int[10];
然后保证下次使用res变量时其他线程会捡到它。
在这种特殊情况下,您只是重置为零并且不依赖于res 的先前值,这可能已经足够了。
如果您确实依赖于先前的值(或其他共享变量),则需要在线程之间实现进一步的同步。
但是有一个警告:其他线程可能仍在操作您的“copy”变量中的值,因为它们可能已经检索到引用并持有它。
【解决方案2】:
没有某种形式的同步是不安全的。
一个线程是否可以在其他线程更新数组时执行示例中显示的引用交换?如果是这样,那么该代码非常不安全,因为不同的线程可能不同意res 引用的数组,因此更新可能会丢失。
即使更新数组的唯一线程与执行交换的线程相同,代码仍然也不安全,因为其他线程可能会看到对数组成员的更新发生乱序相对于彼此,并且相对于res的重新分配是无序的。
您应该保护 所有 访问(来自 任何 线程)对 res 和对数组成员的锁定。