java线程锁同步问题,刚接触线程锁,出错了,代码很少,请看
[code=java
/**
* 被打的人
*
* @author zhaozhantao@21cn.com
*
*/
public class ManBall extends Spirit {
/**
* 能被碰撞的东西
*/
private List<Collideable> collideables = new ArrayList<Collideable>();
@Override
public void move(float x, float y) {
synchronized (collideables) {
if (collideables != null) {
for (Collideable collideable : collideables) {
if (collideable.checkCollide(this, (int) x, (int) y)) {
CollideEvent collideEvent = new CollideEvent();
collideEvent.setCollideable(collideable);
collideListener.onCollide(collideEvent);
}
}
}
}
super.move(x, y);
}
][/code]
------解决方案--------------------你看看
在执行for (Collideable collideable : collideables) {}的时候
里面的代码,比如
collideEvent.setCollideable(collideable);
collideListener.onCollide(collideEvent);
这两句会不会去调用addCollideable或者removeCollideable
或者对collideables执行其他删除、添加元素的方法。
在你遍历的时候collideables,如果有这种操作,就会产生
java.util.ConcurrentModificationException
这个我以前碰到过。
------解决方案--------------------
问题不在synchronized 而在于
你对集合遍历的时候的对集合元素进行了删除操作 即使你锁了,也是不允许这么做的。
不知道你能否理解
------解决方案--------------------你可以再定义一个集合private List<Collideable> collideables2 = new ArrayList<Collideable>();把原来的集合copy过来collideables2 = collideables?然后对这个集合进行遍历for(int i=0;i<collideables2.size();i++),获取对象的时候通过索引i去获取,注意你循环里面的操作对象通过i去原来的集合collideables里面拿,就是collideables.get(i)
------解决方案--------------------在遍历ArrayList的时候,对它进行add,remove等操作就会报
ConcurrentModificationException异常,因为原来的结构已经改变,为了防止将来可能出现的未知的错误,java提前抛出这个异常,来提示你数据结构已经改变,如果想要不抛出这个异常,可以使用迭代器的remove方法,跟锁应该是没有关系的,整个程序也没有看到多线程的地方。