Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java和同步两个线程_Java_Synchronization - Fatal编程技术网

Java和同步两个线程

Java和同步两个线程,java,synchronization,Java,Synchronization,我有两个线程修改相同的对象。对象是ArrayList中的自定义非同步对象(不是向量)。我想让这两个线程很好地协同工作,因为它们是同时被调用的 这里是线程1中唯一重要的方法 public void doThread1Action() { //something... for(myObject x : MyArrayList){ modify(x); } } 以下是线程2中的一个方法: public void doThread2Action() { //somethi

我有两个线程修改相同的对象。对象是
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
?或者我应该将
数组列表
更改为
向量

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

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


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

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

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

void modifyAgain(MyObject x) {
    synchronized(x) {
        // do the modification
    }
}
我不会在
modifyreach()
方法上使用
synchronized
修饰符,因为这不允许同时修改列表中的两个不同对象


当然,另一个线程中的
modify()
方法的实现方式必须与
modifyreach()

相同,您需要在同一个锁上同步对集合的访问,因此仅在方法上使用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);
    }

}

也可以考虑使用<代码> CopyOnWorksRayList而不是<代码> vector < /COD>

< P>我猜您的问题与 > CONTRONMODIFICIONTUCTION/COD>有关。该类在其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);
       }
    }
}
为了取得更好的结果,我希望任何人都能纠正我的解决方案