小编Mar*_*šić的帖子

Java ConcurrentHashMap.computeIfPresent值修改可见性

假设我有一个带有集合的并发映射值:

Map<Integer, List<Integer> map = new ConcurrentHashMap<>();
map.putIfAbsent(8, new ArrayList<>());
Run Code Online (Sandbox Code Playgroud)

我更新了如下值:

map.computeIfPresent(8, (i, c) -> {
    c.add(5);
    return c;
});
Run Code Online (Sandbox Code Playgroud)

我知道computeIfPresent整个方法调用是以原子方式执行的.但是,考虑到这个映射是由多个线程同时访问的,我有点担心对底层集合所做的修改的数据可见性.在这种情况下,调用后将在列表中看到值5map.get

我的问题是map.get如果在computeIfPresent方法调用中执行了更改,则在调用时将更改为列表在其他线程中可见.

请注意,如果我在执行更新操作之前参考列表,我知道列表的更改将不可见.如果我map.get在更新操作后引用列表(通过调用),我不确定列表的更改是否可见.

我不确定如何解释文档,但在我看来发生这种情况 - 在关系之前将保证在这种特定情况下对底层集合的更改的可见性

更正式地说,给定密钥的更新操作承担与该密钥的任何(非空)检索之前发生的关系,报告更新的值

java multithreading concurrenthashmap memory-visibility

14
推荐指数
1
解决办法
460
查看次数

java中的同步重新排序

众所周知,JVM不应该将带有同步块的语句重新排序到同步块之外.考虑到这一点,是否允许JVM重新排序在下面的代码段中y = 7synchronized块之后发生的分配?

x = 5;
y = 7;
synchronized (this) {
    x = 6;
}
Run Code Online (Sandbox Code Playgroud)

我们知道在同步块之前的变量赋值可以重新排序以在块内发生.所以以下内容应该是初始代码的有效重新排序:

x = 5;
synchronized (this) {
    x = 6;
    y = 7;
}
Run Code Online (Sandbox Code Playgroud)

有人可能会争辩说,因为这是一个有效的排序,y所以在synchronized块之后不能进行赋值,因为它会违反规则,即在块之后不得重新排序来自同步块内的代码并推断出在同步y 结束之前发生的情况.块.

另一方面,可能所有的排序都不等同,而且排序是实际的排序也很重要.具体来说,如果y赋值最初是在同步块内完成的,则在块之后不会发生,否则就可能发生.

总结一下,接下来是订购第一个片段的有效排序吗?

x = 5;
synchronized (this) {
    x = 6;
}
y = 7;
Run Code Online (Sandbox Code Playgroud)

java synchronized

4
推荐指数
1
解决办法
114
查看次数