ConcurrentModificationException即使在使用synchronized时也是如此

时间:2014-10-24 08:33:48

标签: java android multithreading

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

我收到以下错误:

java.util.ConcurrentModificationException at java.util.AbstractList$SimpleListIterator.next(AbstractList.java:95) at com.convekta.android.chessboard.ChessBoard.renderGamerPieces(ChessBoard.java:424) at com.convekta.android.chessboard.ChessBoard.render(ChessBoard.java:162) at com.convekta.android.chessboard.ChessDrawThread.run(ChessDrawThread.java:41)

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

也许我不明白。那么这个错误可能会出现怎么样?

我的代码:

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

1 个答案:

答案 0 :(得分:0)

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