java - 当两个线程同时执行cache.putIfAbsent时会发生什么?

标签 java multithreading concurrency concurrenthashmap futuretask

我正在学习Java并发实践,但有些代码让我困惑:

private final ConcurrentHashMap<A, Future<V>> cache = new ConcurrentHashMap<A, Future<V>>();

private final Computable<A, V> c;

public Memoizer(Computable<A, V> c) {
    this.c = c;
}

/* (non-Javadoc)
 * @see com.demo.buildingblocks.Computable#compute(java.lang.Object)
 */
@Override
public V compute(final A arg) throws InterruptedException {

    while (true) {
        Future<V> f = cache.get(arg);
        if (f == null) {
            // 
            Callable<V> eval = new Callable<V>() {
                @Override
                public V call() throws Exception {
                    return c.compute(arg);
                }
            };
            FutureTask<V> ft = new FutureTask<V>(eval);
            // what will happen when two threads arrive here at the same time?
            f = cache.putIfAbsent(arg, ft);
            if (f == null) {
                f = ft;
                ft.run();
            }
        }
        try {
            return f.get();
        } catch (CancellationException e) {
            cache.remove(arg, f);
        } catch (ExecutionException e) {
            launderThrowable(e);
        }
    }
}

我就是无法理解,因为putIfAbsent只能保证put操作是原子的,并且如果两个线程都能进入它们都返回null >运行方法?

最佳答案

putIfAbsent 保证线程安全,不仅是因为它不会损坏您的数据,而且还因为它始终在最新的情况下工作数据的日期副本。

此外,如果存在这样的值,它不会返回 map 中的先前值。因此,第一次调用 putIfAbsent 将会成功,并返回 null,因为没有先前的值。第二个调用将阻塞,直到第一个调用成功,然后返回放入映射中的第一个值,导致第二个 run() 永远不会被调用。

关于java - 当两个线程同时执行cache.putIfAbsent时会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20171896/

相关文章:

java - spring处理POST数据-注释正确的 Controller

java - 使用log4j在 Multi-Tenancy 应用程序中根据租户将日志写入不同日志文件的方法

java - JBullet - 静态时凸形状无法正常工作

java - java中的synchronized关键字

sql - SET NOCOUNT ON 使用情况

java - 如何在并发事务中实现高性能的对象隔离解决方案

java - 可以将具有 Function 字段的 Java 类视为不可变的吗?

c# - 适用于 .NET 的 Node.js

java - 线程如何工作

java - 优化/并发 JAVA : reading CSV file, 解析数据以加倍然后对值进行计算