Java ConcurrentModificationException,即使使用同步

Java ConcurrentModificationException,即使使用同步,java,android,multithreading,Java,Android,Multithreading,我有两个线程:第一个线程是渲染线程,第二个线程是处理UI操作的主线程 我得到以下错误: java.util.ConcurrentModificationException 位于java.util.AbstractList$SimpleListIterator.nextAbstractList.java:95 在com.convekta.android.chessboard.chessboard.renderGamerPiecesChessBoard.java:424 位于com.convekta

我有两个线程:第一个线程是渲染线程,第二个线程是处理UI操作的主线程

我得到以下错误:

java.util.ConcurrentModificationException 位于java.util.AbstractList$SimpleListIterator.nextAbstractList.java:95 在com.convekta.android.chessboard.chessboard.renderGamerPiecesChessBoard.java:424 位于com.convekta.android.chessboard.chessboard.renderChessBoard.java:162 位于com.convkta.android.chessboard.ChessDrawThread.runChessDrawThread.java:41

ConcurrentModification异常的常见原因是迭代列表的更改,但我只在renderGamerPieces函数中读取它。mGamerPieces唯一可能更改的地方是loadPosition方法,但loadPosition和renderGamerPieces都在同步块内调用

也许我不明白什么。。那么这个错误是如何出现的呢

我的代码:

private final List<DrawablePiece> mGamerPieces = new ArrayList<DrawablePiece>();
private final Object mGamerPiecesLock = new Object();

public void loadPosition(byte[] pieces, byte[] places) {
        synchronized (mGamerPiecesLock) {
            mPicked = null;
            mGamerPieces.clear();
            for (int i = 0; i < pieces.length; i++) {
                byte p = GamerUtils.UncastleRook(pieces[i]);
                if (p != GamerPieces.EMPTY) {
                    byte pl = places[i];
                    if (pl <= GAME_BOARDSIZE)
                        mGamerPieces.add(new DrawablePiece(p,
                                GamerUtils.columnByCell(pl), GamerUtils.rowByCell(pl,
                                        true)));
                }
            }
        }
    }

public void renderGamerPieces(Canvas canvas) {
    ...
    Rect r = new Rect(0, 0, mCellSize, mCellSize);
    List<DrawablePiece> over = new ArrayList<DrawablePiece>();

    for (DrawablePiece d : mGamerPieces) {
        if (d.isFloating()) {
            over.add(d);
        } else {
            r.offsetTo(invert(d.getBoardCol()) * mCellSize,
                    invert(d.getBoardRow()) * mCellSize);
            r.offset(mBoardRegion.left, mBoardRegion.top);
            Bitmap pic = mPieceFactory.getBitmapPiece(d.getPiece(),
                    mCellSize);
            if (null != pic)
                canvas.drawBitmap(pic, null, r, null);
        }
    }
    ...
 }

public void render(Canvas canvas) {
        ...
        synchronized (mGamerPiecesLock) {
            renderGamerPieces(canvas);
        }
        ...
}

谢谢你的评论!我将整理我的代码-在renderGamerPieces中添加同步块,并检查是否可以从另一个同步块调用loadPosition。

我通过使同步块尽可能小来进行代码重构,问题得到了解决。显然,随后有一个从一个同步块到另一个块的调用。

loadPosition是从RenderGamePieces调用的吗?不,loadPosition是从其他类调用的,而不是从这个类调用的。唯一合理的解释是,您忽略了一些东西。下面是我在黑暗中拍摄的照片:renderGamePieces是公共的,但您不能在该方法中同步。您可能是从其他地方调用它,在那里您不同步。即使这不是问题所在,您也应该从该方法中进行同步,因为这对其正确性至关重要。从堆栈跟踪开始,它是从呈现调用的。作为解决方法,您可以使用CopyOnWriteArrayList。