Java 如何构造非重复列表?
我想用下面的代码构造一个不重复的列表,但有些地方出错了,有人说它是线程不安全的,但我不明白,所以请给我一些例子来证明它,谢谢Java 如何构造非重复列表?,java,thread-safety,Java,Thread Safety,我想用下面的代码构造一个不重复的列表,但有些地方出错了,有人说它是线程不安全的,但我不明白,所以请给我一些例子来证明它,谢谢 class BadListHelper <E> { public List<E> list = Collections.synchronizedList(new ArrayList<E>()); public synchronized boolean putIfAbsent(E x) { bo
class BadListHelper <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;
}
}
类BadListHelper{
public List=Collections.synchronizedList(新的ArrayList());
公共同步布尔putIfAbsent(ex){
布尔缺席=!list.contains(x);
如果(缺席)
增加(x);
缺席返回;
}
}
代码的一个问题是(公开的)列表
对象上的操作和putIfAbsent
方法在不同的对象上同步。这意味着putIfAbsent
对于list
上的直接操作具有竞争条件
例如,如果您有两个线程:
- 线程A调用helper.list.add(e)
- 线程B调用helper.putIfAbsent(e)
e
。。。视时间而定
public synchronized boolean putIfAbsent(E x) {
boolean absent = !list.contains(x);
// <<--- the Thread A call could happen here.
if (absent) {
list.add(x);
}
return absent;
}
什么是“非重复列表”?什么是“不对劲”?预期和实际行为是什么?为什么不使用
集合
?更具体地说是一个LinkedHashSet
(如果您想保持插入顺序)?@anacron它必须类似于LinkedHashSet
,以确保顺序。我只是不明白问题出在哪里,很抱歉,我没有表达我自己clearly@OldCurmudgeon-这是不安全的。。。请参阅我的答案以了解解释谢谢我的朋友,但是“public synchronized boolean putIfAbsent(ex)”意味着在当前方法完成之前,另一个线程无法调用此方法,因此为什么会出现多线程问题呢?synchronized
方法调用只排除在this
上同步的其他方法调用。这是与列表
不同的对象。因此,不排除列表中的方法调用
public boolean putIfAbsent(E x) {
synchronized (list) {
boolean absent = !list.contains(x);
if (absent) {
list.add(x);
}
return absent;
}
}