Java同步列表

时间:2012-07-06 10:25:16

标签: java multithreading

我有一个预先填充的数组列表。我有多个线程将从数组列表中删除元素。每个线程调用下面的remove方法,并从列表中删除一个项目。以下代码是否给我一致的行为?

ArrayList<String> list = Collections.synchronizedList(new ArrayList<String>());

void remove(String item)
{
     do something; (doesn't work on the list)
     list.remove(item);
}

谢谢!

7 个答案:

答案 0 :(得分:62)

是的,如果您也在遍历列表,请小心,因为在这种情况下,您需要对其进行同步。来自Javadoc

  

当迭代时,用户必须手动同步返回的列表:

List list = Collections.synchronizedList(new ArrayList());
    ...
synchronized (list) {
    Iterator i = list.iterator(); // Must be in synchronized block
    while (i.hasNext())
        foo(i.next());
}

或者,您可以使用CopyOnWriteArrayList,这对写入速度较慢,但​​没有此问题。

答案 1 :(得分:23)

只要你不要求“删除”方法是原子的,这应该没问题。

换句话说,如果“执行某事”检查项目在列表中出现多次,那么当您到达下一行时,该检查的结果可能会出错。

另外,请确保在迭代时在列表上进行同步:

synchronized(list) {
    for (Object o : list) {}
}

如Peter Lawrey所述,CopyOnWriteArrayList可以让您的生活更轻松,并可在高度并发的环境中提供更好的表现。

答案 2 :(得分:11)

来自Collections#synchronizedList(List) javadoc

  

返回由指定的支持的同步(线程安全)列表   名单。为了保证串行访问,至关重要的是   完成后备列表的所有访问权限   通过返回的列表...当迭代时,用户必须手动同步返回的列表。不遵循此建议可能会导致非确定性行为。

答案 3 :(得分:2)

列表可能存在2个不同的问题:
1)如果在迭代中进行修改,即使在单线程环境中,您将具有ConcurrentModificationException,如下面的示例所示:

List<String> list = new ArrayList<String>();
for (int i=0;i<5;i++)
   list.add("Hello "+i);

for(String msg:list)
   list.remove(msg);

所以,为了避免这个问题,你可以这样做:

for(int i=list.size()-1;i>=0;i--)
   list.remove(i);

2)第二个问题可能是多线程环境。如上所述,您可以使用synchronized(list)来避免异常。

答案 4 :(得分:0)

它将为添加/删除操作提供一致的行为。但是在迭代时你必须明确地同步。 Refer this link

答案 5 :(得分:0)

是的,它会正常工作,因为您有synchronized列表。我建议你使用CopyOnWriteArrayList

CopyOnWriteArrayList<String> cpList=new CopyOnWriteArrayList<String>(new ArrayList<String>());

    void remove(String item)
    {
         do something; (doesn't work on the list)
                 cpList..remove(item);
    }

答案 6 :(得分:-4)

synchronized(list) {
    for (Object o : list) {}
}