Java和同步两个线程

时间:2012-05-12 10:59:13

标签: java synchronization

我有两个线程修改相同的对象。对象是ArrayList中的自定义非同步对象(不是向量)。我想让这两个线程很好地协同工作,因为它们同时被调用。

这是线程1中唯一重要的方法。

public void doThread1Action() {
  //something...
  for(myObject x : MyArrayList){
    modify(x);
  }
}

以下是主题2中的方法:

public void doThread2Action() {   
  //something...
  for(myObject x : MyArrayList){
    modifyAgain(x);
  }
}

目前,在测试时,我偶尔会得到`ConcurrentModificationExceptions``。 (我认为这取决于线程1在线程2尝试修改对象之前完成迭代的速度有多快。)

我是否正确地认为只需将synchronized附加到这两个方法的开头,线程就会以同步方式一起工作,而不是尝试访问ArrayList?或者我应该将ArrayList更改为Vector

4 个答案:

答案 0 :(得分:3)

ConcurrentModificationException不是源于修改集合中的对象,而是源于在迭代器处于活动状态时从集合中添加/删除。

共享资源是集合,必须有第三种方法使用和添加/删除。要获得正确的并发性,必须在访问它的所有方法中同步对集合资源的访问。

为了避免过长的同步块,常见的模式可能是在同步块中复制集合,然后迭代它。如果你这样做,请注意你首先讨论的问题(并发修改你的对象)再次就位 - 但这次你可以锁定另一个资源。

答案 1 :(得分:0)

只要不从结构上修改它,即只要不从列表中添加或删除对象,就不需要同步对列表的访问。您也不应该看到ConcurrentModificationException,因为只有在您从结构上修改列表时才会抛出这些内容。

因此,假设您只修改列表中包含的对象,但是您没有在列表中添加或删除或重新排序对象,则可以在修改它们时对包含的对象进行同步,如下所示:

void modifyAgain(MyObject x) {
    synchronized(x) {
        // do the modification
    }
}

我不会在synchronized方法上使用modifyAgain()修饰符,因为它不允许同时修改列表中的两个不同对象。

其他线程中的modify()方法当然必须以与modifyAgain()相同的方式实现。

答案 2 :(得分:0)

您需要对同一个锁上的集合进行sychronsize访问,因此只需在方法上使用synchronized关键字(假设它们位于不同的类中)就会锁定两个不同的对象。

所以这里有一个你可能需要做的例子:

Object lock = new Object();

public void doThread1Action(){

//something...
    synchronized(lock){
        for(myObject x : MyArrayList){
           modify(x);
    }

}

public void doThread2Action(){

//something...
    synchronized(lock){
        for(myObject x : MyArrayList){
            modifyAgain(x);
    }

}

您也可以考虑使用CopyOnWriteArrayList代替Vector

答案 3 :(得分:0)

我猜您的问题与ConcurrentModificationException有关。这个类在其Java文档中说:

  

/ **
  *此异常可能由检测到的方法引发   同时
  *当没有这样的修改时修改对象   允许的。

     

* /

在您的情况下,问题是列表中的迭代器,可能会被修改。我想通过以下实施,你的问题将是唯一的:

public void doThread1Action()
{
    synchronized(x //for sample)
    {
       //something...
       for(myObject x : MyArrayList)
       {
          modify(x);
       }
    }
}

然后:

public void doThread2Action()
{
    synchronized(x //for sample)
    {
       //something...
       for(myObject x : MyArrayList)
       {
          modifyAgain(x);
       }
    }
}

为了获得更好的结果,我希望任何人都能纠正我的解决方案。