Java 如何正确使用synchronized?
这段代码:Java 如何正确使用synchronized?,java,android,synchronized,synchronized-block,Java,Android,Synchronized,Synchronized Block,这段代码: synchronized (mList) { if (mList.size() != 0) { int s = mList.size() - 1; for (int i = s; i > 0; i -= OFFSET) { mList.get(i).doDraw(canv); } getHead().drawHead(canv); } } 随机抛出AIOOBEs。从我所读到
synchronized (mList) {
if (mList.size() != 0) {
int s = mList.size() - 1;
for (int i = s; i > 0; i -= OFFSET) {
mList.get(i).doDraw(canv);
}
getHead().drawHead(canv);
}
}
随机抛出AIOOBEs。从我所读到的,同步应该可以防止这种情况,那么我做错了什么
编辑:
AIOOBE=数组索引超出边界异常
代码不完整,减少到需要的程度。但为了让您满意,偏移量是4,想象一下有一个for循环在开始时添加了一些数据。以及第二线程读取和/或修改列表
编辑2:
我注意到,当列表被绘制出来,当前游戏结束时,就会发生这种情况。当列表为空时,绘制线程尚未绘制所有元素。有没有一种方法可以告诉游戏等待列表变为空
编辑3:
我刚刚注意到,我不确定这是否是一个多线程问题。似乎我只有两个线程,一个用于计算和绘图,一个用于用户输入。。我必须比我想象的更深入地调查这件事。你所做的看起来是对的。。。但仅此而已:
同样:对共享资源的任何访问都必须受到某种保护。似乎您正在使用的是
synchronized
,而不是清空列表的位置。您得到的是索引越界异常,因为有两个线程在列表上操作,并且操作错误。
您应该在另一个级别进行同步,这样当其他线程正在修改列表时,其他线程就不能遍历列表了!一次只能在线程上“处理”列表
我猜你有以下情况:
//在列表中添加某些项的代码段
synchronized(mList){
mList.add(1, drawableElem);
...
}
及
//迭代列表的代码(简化代码)
单独使用代码片段看起来不错。他们缝线安全。但是,在更高的级别上,两段单独的线程安全代码可能不是线程安全的!
只是你应该做以下几件事:
Vector v = new Vector();
if(v.length() == 0){ v.length() itself is thread safe!
v.add("elem"); v.add() itself is also thread safe individually!
}
但复合操作不是强>
问候,,
提比略安全的解决方案是只允许一个线程创建对象,在游戏开始后从列表中添加和删除对象 我自己也遇到了随机AIOOBEs错误的问题,没有synchornize能够正确地解决它,而且它会减慢用户的响应速度 我的解决方案现在稳定且快速(从那时起就没有AIOOBEs)是让UI线程通知游戏线程通过在持久变量中设置一个标志和触摸坐标来创建或操作一个对象 由于游戏线程每秒循环大约60次,这足以从UI线程获取消息并执行某些操作 这是一个非常简单的解决方案,效果非常好 我的建议是使用a,我想您也在寻找这个解决方案。你怎么能做到?javadoc中的示例已经显示了它:) 对您有益的是,您不必担心同步
mList
BlockingQueue
提供10种特殊方法。你可以在单据上查一下。javadoc中的一些:
BlockingQueue方法有四种形式,有不同的处理操作的方法,这些操作不能立即满足,但在将来的某个时候可能会满足:一种抛出异常,另一种返回特殊值(null或false,取决于操作),第三个线程无限期地阻塞当前线程,直到操作成功,第四个线程在放弃之前只阻塞给定的最大时间限制
为了安全起见:我对安卓没有经验。所以不确定android是否允许所有java包。但至少应该是:-S,我希望如此。IOORE?请扩展到一个完整的异常名称-我敢说,我们可以在一段时间后理解您的意思,但如果您真的告诉我们从开始,它会简单得多。您的代码看起来不完整。数据添加到列表中的位置(以及删除的位置)?什么是偏移量?如果是你说的
数组索引超出边界异常
,我通常将其缩写为aioobe;-)我能看到的唯一一件事是,如果doDraw(canv)从同一列表中删除多个对象,那么如果偏移量=1与您的问题无关,则下一个I将不存在:您确定要I>0而不是I>=0
?是的,第2点。这真的很重要@SBoss我们看不到使用mList
的代码的其余部分,但是访问或修改mList
的每个代码段都必须受到synchronized(mList)
的保护。只同步代码的一部分是完全无用的。这样我就可以写synchronize()?2.谢谢,我不知道。我会检查我的密码。3.AWT?@SBoss No,如果您在实例MyClass class1
和MyClass class2
中有围绕mList
同步(this)
,this
锁在两个不同的锁上,就mList
而言,不会有同步。@SBoss回答Edit2:你必须在游戏结束时同步清空列表的代码块!每次使用mList
,都必须同步代码;你会的
Vector v = new Vector();
if(v.length() == 0){ v.length() itself is thread safe!
v.add("elem"); v.add() itself is also thread safe individually!
}
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
class Setup {
void main() {
BlockingQueue q = new SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}