gpt4 book ai didi

java - 非线程安全尝试实现 Put-if-absent?

转载 作者:行者123 更新时间:2023-12-02 05:55:55 26 4
gpt4 key购买 nike

《Java并发实践》第4章有一段代码

public class ListHelper<E> {
public List<E> list =
Collections.synchronizedList(new ArrayList<E>());
...
public synchronized boolean putIfAbsent(E x) {
boolean absent = !list.contains(x);
if (absent)
list.add(x);
return absent;
}
}

它表示使用不同的锁是线程安全的,putIfAbsent 相对于列表上的其他操作不是原子的。但我认为“synchronized”可以防止多线程进入putIfAbsent,如果还有其他方法对List进行其他操作,关键字synchronized也应该作为方法属性。那么按照这种方式,它应该是线程安全的吗?什么情况下“它不是原子的”?

最佳答案

putIfAbsent is not atomic relative to other operations on the List. But I think "synchronized" preventing multithreads enter putIfAbsent

这是事实,但不能保证线程可以通过其他方式访问列表list 字段是 public (这始终是一个坏主意),这意味着其他线程可以直接调用 list 上的方法。为了正确保护列表,您应该将其设置为私有(private),并将add(...)和其他方法添加到您的ListHelper中,这些方法也是synchronized 以完全控制对同步列表的所有访问。

// we are synchronizing the list so no reason to use Collections.synchronizedList
private List<E> list = new ArrayList<E>();
...
public synchronized boolean add(E e) {
return list.add(e);
}

如果列表是私有(private)并且所有访问该列表的方法都已同步,那么您可以删除Collections.synchronizedList(...),因为您正在同步自己做吧。

if there are other methods that do other operations on the List, key word synchronized should also be as the method atttribute. So following this way, should it be thread safe?

不确定我是否完全解析了问题的这一部分。但是,如果您将列表设置为私有(private),并且添加其他方法来访问全部同步的列表,那么您是正确的。

Under what case "it is not atomic"?

putIfAbsent(...) 不是原子的,因为对同步列表有多次调用。如果多个线程正在对列表进行操作,则另一个线程可能在 putIfAbsent(...) 调用 list 的时间之间调用了 list.add(...) .contains(x),然后调用list.add(x)Collections.synchronizedList(...) 可以保护列表免受多个线程的损坏,但当对列表方法的多个调用可能与其他线程的调用交错时,它无法防止竞争条件。

关于java - 非线程安全尝试实现 Put-if-absent?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23086236/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com