2013-08-01 48 views
14

返回一个列表,我发现这个在dos.oracle.com为什么我需要同步由Collections.synchronizedList

公共静态列表synchronizedList(名单列表)

返回的同步(线程安全)列表支持指定的 列表。为了保证串行访问,通过返回列表完成对后备列表访问的所有访问是至关重要的。 当务之急是用户迭代它时,返回 名单上手动同步:

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

我的问题是:为什么我必须同步列表进行迭代,如果Collections.synchronizedList();应该返回已经同步列表?

我只是在两个线程访问列表:一个线程只是添加和另一个线程获取和删除。你推荐哪些其他课程用于这种情况?

感谢您的阅读。

+0

我wouldnt使用'Collections.synchronizedList()'。在自己的代码中自己同步可能会更好 – JIV

回答

17

正在同步的列表仅意味着add,remove等操作是同步的,因此是原子的。然而,迭代不是,如果一个线程adds而另一个正在迭代,则可能会发生ConcurrentModificationException。

通过手动同步您的迭代块,可以确保迭代时列表不会被修改。

一个替代方案是使用a CopyOnWriteArrayList,其提供an iterator,超过列表迭代,因为它是已知的当迭代开始,而不管随后的修饰。但是,如果您需要经常更改列表的内容,那么该集合效率不高。

+0

谢谢!我会赞成它,但我没有足够的声誉。 CopyOnWriteArrayList听起来不错,但是,是一个非常经常的过程,CopyOnWriteArrayList可能会有点慢。 – GabrielBB

+0

+1。你怎么知道'add','remote'等是同步的?在javadoc中没有任何关于它的内容。 –

+0

@LuisSep你可以得出这样的结论:基于javadoc说列表已同步,并且迭代应该获取列表的监视器(这与正在同步的方法一致)。看看执行情况就可以确认它。 – assylias

-1

起初我对这个话题感到困惑,因为我发现的大多数例子都没有上下文。我终于找到了这个博客文章,为我清除了一些东西:http://netjs.blogspot.de/2015/09/how-and-why-to-synchronize-arraylist-in-java.html

从上面的例子看来,我只需要将我的列表与Collections.synchronizeList(),然后我可以添加和删除项目,而无需担心线程安全。但是在这里需要注意的是,必须在将列表传递给不同的线程之前对其进行同步,因为否则列表访问不是互斥的。

因此,一个完整的例子是:

public class SynchroProblem implements Runnable{ 
    private List<Integer> myList; 

    //Constructor 
    public SynchroProblem(List<Integer> myList){ 
    this.myList = myList; 
    } 

    @Override 
    public void run() { 
    // Do stuff with the list .add(), .remove(), ... 
    myList.add(5); 

    // Even if mylist is synchronized the iterator is not, 
    // so for using the iterator we need the synchronized block 
    synchronized (myList){ 
     // do stuff with iterator e.g. 
     Iterator<Integer> iterator = myList.iterator(); 
     while (iterator.hasNext()){ 
     int number = iterator.next(); 
     if (number == 123){ 
      iterator.remove(); 
     } 
     } 

    } 
    } 

    public static void main(String[] args) { 

    List<Integer> originalList = new ArrayList<Integer>(); 

    // Synchronize list 
    List<Integer> syncList = Collections.synchronizedList(originalList); 

    // Create threads and pass the synchronized list 
    Thread t1 = new Thread(new SynchroProblem(syncList)); 
    Thread t2 = new Thread(new SynchroProblem(syncList)); 

    t1.start(); 
    t2.start(); 

    } 
} 
相关问题