gpt4 book ai didi

java - 为什么这段代码不是线程安全的,即使在使用同步方法时也是如此?

转载 作者:行者123 更新时间:2023-11-29 09:37:57 24 4
gpt4 key购买 nike

为什么这段代码不是线程安全的,即使我们使用同步方法并因此获得了对 Helper 对象的锁定?

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;
}
}

最佳答案

因为当 contains 返回时列表被解锁,然后当调用 add 时再次锁定。其他东西可以在两者之间添加相同的元素。

如果您的意思是仅使用辅助对象中的列表,则应将其声明为private;如果这样做,代码将是线程安全的,只要对列表的所有操作都通过辅助对象中同步的方法进行。还值得注意的是,只要是这种情况,您就不需要使用 Collections.synchronizedList,因为您在自己的代码中提供了所有必要的同步。

或者,如果您想允许列表公开,您需要同步您对列表的访问,而不是对您的帮助对象的访问。以下将是线程安全的:

class ListHelper <E> {
public List<E> list = Collections.synchronizedList(new ArrayList<E>());

public boolean putIfAbsent(E x) {
synchronized (list) {
boolean absent = !list.contains(x);
if (absent)
list.add(x);
return absent;
}
}
}

区别在于它使用与列表的其他方法相同的锁,而不是不同的锁。

关于java - 为什么这段代码不是线程安全的,即使在使用同步方法时也是如此?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17533263/

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