在实例重新分配期间锁定变量
Locking a variable during instance reassignment
假设我有两个线程:Thread-A
和 Thread-B
Thread-A
计划更新其 class:
中的局部变量
public class SomeClass {
private List<String> aSpecialList = new ArrayList<>();
@Scheduled(....)
public void updateASpecialList() {
List<String> aBetterSpecialList = new ArrayList<>()
// all these great things happen to aBetterSpecialList
...
aSpecialList = aBetterSpecialList;
}
public List<String> getASpecialList() {
return aSpecialList;
}
}
现在,Thread-B
在 Thread-A
即将执行变量重新分配时尝试访问此列表 (SomeClass::getASpecialList()
)。如果我不锁定 aSpecialList
?
是否有可能导致任何形式的并发问题
既然aSpecialList
是不可变的,那么aSpecialList = aBetterSpecialList
就是an unsafe publication。
因此,当 Thread-B
读取 aSpecialList
.
时,我们不会得到所谓的 happen-before
关系(来自 JMM 的术语)
结果我们遇到了以下并发问题(也称为数据竞争):
Thread-B
对 aSpecialList
的读取是活泼的:每次独立读取都可能 return 在整个生命周期内任何其他线程写入该字段的任何值程序
Thread-B
对存储在 aSpecialList
中的 ArrayList
中的任何字段的任何读取也是活泼的。
例如,Thread-B
可以看到 size
of the ArrayList
and its internalelementData
数组的值不一致。
其中一个解决方案是使 aSpecialList
易变,然后:
Thread-B
保证可以看到 Thread-A
对 aSpecialList
的写入
Thread-B
也保证可以看到 ArrayList
存储在 aSpecialList
中的内部状态,就像它在发布时一样
另外我也会把你写的列表写成aSpecialList
immutable.
假设我有两个线程:Thread-A
和 Thread-B
Thread-A
计划更新其 class:
public class SomeClass {
private List<String> aSpecialList = new ArrayList<>();
@Scheduled(....)
public void updateASpecialList() {
List<String> aBetterSpecialList = new ArrayList<>()
// all these great things happen to aBetterSpecialList
...
aSpecialList = aBetterSpecialList;
}
public List<String> getASpecialList() {
return aSpecialList;
}
}
现在,Thread-B
在 Thread-A
即将执行变量重新分配时尝试访问此列表 (SomeClass::getASpecialList()
)。如果我不锁定 aSpecialList
?
既然aSpecialList
是不可变的,那么aSpecialList = aBetterSpecialList
就是an unsafe publication。
因此,当 Thread-B
读取 aSpecialList
.
时,我们不会得到所谓的 happen-before
关系(来自 JMM 的术语)
结果我们遇到了以下并发问题(也称为数据竞争):
Thread-B
对aSpecialList
的读取是活泼的:每次独立读取都可能 return 在整个生命周期内任何其他线程写入该字段的任何值程序Thread-B
对存储在aSpecialList
中的ArrayList
中的任何字段的任何读取也是活泼的。
例如,Thread-B
可以看到size
of theArrayList
and its internalelementData
数组的值不一致。
其中一个解决方案是使 aSpecialList
易变,然后:
Thread-B
保证可以看到Thread-A
对 Thread-B
也保证可以看到ArrayList
存储在aSpecialList
中的内部状态,就像它在发布时一样
aSpecialList
的写入
另外我也会把你写的列表写成aSpecialList
immutable.