Java 什么算修改?

Java 什么算修改?,java,multithreading,arraylist,concurrentmodification,Java,Multithreading,Arraylist,Concurrentmodification,我对多线程比较陌生,我正在尝试在我正在创建的游戏中使用3种不同的线程。一个线程正在执行后端更新,另一个线程正在用于绘图,第三个线程用于加载和/或生成新的块(并在我不需要它们时很快将它们保存下来)。我让draw和update线程正常工作,然后当我将第三个线程添加到混合中时,我开始遇到ConcurrentModificationException的问题。它们发生在我的内心深处,因为。。。所有循环,在其中我通过区块对象的ArrayList循环 我已尝试锁定每个线程何时能够使用Phaser访问和修改ch

我对多线程比较陌生,我正在尝试在我正在创建的游戏中使用3种不同的线程。一个线程正在执行后端更新,另一个线程正在用于绘图,第三个线程用于加载和/或生成新的块(并在我不需要它们时很快将它们保存下来)。我让draw和update线程正常工作,然后当我将第三个线程添加到混合中时,我开始遇到ConcurrentModificationException的问题。它们发生在我的内心深处,因为。。。所有循环,在其中我通过区块对象的ArrayList循环

我已尝试锁定每个线程何时能够使用Phaser访问和修改chunk ArrayList,如下所示:

private volatile ArrayList<Chunk> chunks = new ArrayList<Chunk>();
private volatile int chunksStability = 0; //+'ive = # threads accessing, -'ive = # threads editing
private volatile Object chunkStabilityCountLock = new Object();
private volatile Phaser chunkStabilityPhaser = new Phaser() {
    protected boolean onAdvance(int phase, int registeredParties) {
        synchronized(chunkStabilityCountLock)
        {
            if (registeredParties == 0)
            {
                chunksStability = 0;
            }
            else
            {
                chunksStability = Math.max(Math.min(chunksStability*-1, 1), -1);
            }
        }
        return false;
    }
};

//...

/**
 *  Prevents other threads from editing <b>World.chunks</b>. 
 *  Calling this will freeze the thread if another thread has called <b>World.destabalizeChunks()</b>
 *  without calling <b>World.stabalizeChunks()</b>
 */
public void lockEditChunks()
{
    chunkStabilityPhaser.register();
    if (this.chunkStabilityPhaser.getUnarrivedParties() > 1 && this.chunksStability < 0) //number threads currently editing > 0
    {
        this.chunkStabilityPhaser.arriveAndAwaitAdvance(); //wait until threads editing finish
    }

    synchronized(chunkStabilityCountLock)
    {
        ++this.chunksStability;
    }
}
public void unlockEditChunks()
{
    chunkStabilityPhaser.arriveAndDeregister();
}

/**
 *  Prevents other threads requiring stability of <b>World.chunks</b> from continuing 
 *  Calling this will freeze the thread if another thread has called <b>World.lockEditChunks()</b>
 *  without calling <b>World.unlockEditChunks()</b>
 */
public void destabalizeChunks()
{
    chunkStabilityPhaser.register();
    if (this.chunkStabilityPhaser.getUnarrivedParties() > 1 && this.chunksStability > 0) //number threads currently editing > 0
    {
        this.chunkStabilityPhaser.arriveAndAwaitAdvance(); //wait until threads editing finish
    }

    synchronized(chunkStabilityCountLock)
    {
        --this.chunksStability;
    }
}
public void stabalizeChunks()
{
    chunkStabilityPhaser.arriveAndDeregister();
}
for (int i = 0; i < chunks.size(); ++i)
{
    Chunk c = chunks.get(i);
}
private volatile ArrayList chunks=new ArrayList();
私有易失性int chunksStability=0;//+'ive=#线程访问,-'ive=#线程编辑
私有易失性对象chunkStabilityCountLock=新对象();
专用易失性相器chunkStabilityPhaser=新相器(){
受保护的布尔值onAdvance(整数相位,整数注册方){
已同步(chunkStabilityCountLock)
{
如果(注册方==0)
{
chunksStability=0;
}
其他的
{
chunksStability=Math.max(Math.min(chunksStability*-1,1),-1);
}
}
返回false;
}
};
//...
/**
*阻止其他线程编辑World.chunk。
*如果另一个线程调用了World.destabalizeChunks(),则调用此函数将冻结该线程
*不调用World.stabilizechunks()
*/
public void lockEditChunks()
{
chunkStabilityPhaser.register();
if(this.chunkStabilityPhaser.getUnarrivedParties()>1&&this.chunksStability<0)//当前正在编辑的线程数>0
{
this.chunkStabilityPhaser.arriveAndWaitAdvance();//等待线程编辑完成
}
已同步(chunkStabilityCountLock)
{
++这是稳定性;
}
}
public void unlocketitchunks()
{
chunkStabilityPhaser.arriveAndDeregister();
}
/**
*阻止其他需要稳定World.chunk的线程继续
*如果另一个线程调用了World.lockEditChunks(),则调用此函数将冻结该线程
*不调用World.unlocketitchunks()
*/
公共空间去稳定化块()
{
chunkStabilityPhaser.register();
if(this.chunkStabilityPhaser.getUnarrivedParties()>1&&this.chunksStability>0)//当前正在编辑的线程数>0
{
this.chunkStabilityPhaser.arriveAndWaitAdvance();//等待线程编辑完成
}
已同步(chunkStabilityCountLock)
{
--这是稳定性;
}
}
公共无效StabilizeHunks()
{
chunkStabilityPhaser.arriveAndDeregister();
}
然而,我仍然没有取得任何成功。我想知道我得到并发修改异常的原因是否与我可能对实际的块对象进行修改有关。这将被视为修改,并导致ConcurrentModificationException。我知道我并不是在同一个线程中执行修改,因为异常不会一直被抛出。这让我相信,只有当一个线程(我不知道是哪个线程)在执行过程中到达一个特定点,而另一个线程在chunks ArrayList中迭代时,才会发生错误

我知道简单的解决办法是停止使用。。。所有循环,而是手动执行循环,如下所示:

private volatile ArrayList<Chunk> chunks = new ArrayList<Chunk>();
private volatile int chunksStability = 0; //+'ive = # threads accessing, -'ive = # threads editing
private volatile Object chunkStabilityCountLock = new Object();
private volatile Phaser chunkStabilityPhaser = new Phaser() {
    protected boolean onAdvance(int phase, int registeredParties) {
        synchronized(chunkStabilityCountLock)
        {
            if (registeredParties == 0)
            {
                chunksStability = 0;
            }
            else
            {
                chunksStability = Math.max(Math.min(chunksStability*-1, 1), -1);
            }
        }
        return false;
    }
};

//...

/**
 *  Prevents other threads from editing <b>World.chunks</b>. 
 *  Calling this will freeze the thread if another thread has called <b>World.destabalizeChunks()</b>
 *  without calling <b>World.stabalizeChunks()</b>
 */
public void lockEditChunks()
{
    chunkStabilityPhaser.register();
    if (this.chunkStabilityPhaser.getUnarrivedParties() > 1 && this.chunksStability < 0) //number threads currently editing > 0
    {
        this.chunkStabilityPhaser.arriveAndAwaitAdvance(); //wait until threads editing finish
    }

    synchronized(chunkStabilityCountLock)
    {
        ++this.chunksStability;
    }
}
public void unlockEditChunks()
{
    chunkStabilityPhaser.arriveAndDeregister();
}

/**
 *  Prevents other threads requiring stability of <b>World.chunks</b> from continuing 
 *  Calling this will freeze the thread if another thread has called <b>World.lockEditChunks()</b>
 *  without calling <b>World.unlockEditChunks()</b>
 */
public void destabalizeChunks()
{
    chunkStabilityPhaser.register();
    if (this.chunkStabilityPhaser.getUnarrivedParties() > 1 && this.chunksStability > 0) //number threads currently editing > 0
    {
        this.chunkStabilityPhaser.arriveAndAwaitAdvance(); //wait until threads editing finish
    }

    synchronized(chunkStabilityCountLock)
    {
        --this.chunksStability;
    }
}
public void stabalizeChunks()
{
    chunkStabilityPhaser.arriveAndDeregister();
}
for (int i = 0; i < chunks.size(); ++i)
{
    Chunk c = chunks.get(i);
}
for(int i=0;i
然而,我担心当块对象在arraylist中移动时,这会导致屏幕上偶尔出现抽搐行为。我不想在所有线程之间完全同步对它的访问,因为这会影响性能,而且这可能是一个相当大的项目,需要尽可能提高效率。此外,如果两个线程不使用迭代器或不需要它的稳定性,我没有任何理由阻止它们修改Chunk ArrayList,也没有任何理由阻止两个线程在没有任何修改的情况下同时遍历列表

有关文件的更完整副本:




理想情况下,您应该使代码速度如此之快,以便可以在帧之间加载块。您应该能够设计这样的暂停,使暂停不会超过几毫秒,并且一切仍然平稳运行。这样,用户可以快速加载块,而不必处理多线程代码和追逐竞争条件

如果事实证明您必须使用线程,那么将其限制为它们之间共享的最小可变状态。理想情况下,您将有两个队列,一个具有加载请求,另一个具有加载级别。这两个队列应该是这些线程通信的唯一方式。一旦某个对象被发送到另一个线程,源线程就不应该再以任何方式使用它。这样可以避免竞争条件,而无需添加同步


要更直接地回答您的问题:
ConcurrentModificationException
仅在您修改集合时发生。修改存储在其中的元素不会影响列表本身


我高度怀疑你的同步代码有问题。它看起来不必要的复杂。在当前形式中,一次只能有一个线程访问
块。其他人必须等待轮到他们。在这种情况下完全没有必要。这是一个简单同步块的工作,或者在最坏的情况下,读写锁。

你应该考虑不可变的对象。另外一种方法,再次取决于逻辑可能在副本上有一个循环:最终块[]拷贝=块。to数组(新块(0));用于(块c:复制)。在你的情况下,这可能是好的,也可能是完全错误的,你必须检查谁以及为什么修改列表,我觉得你没有