【发布时间】:2015-07-10 20:56:45
【问题描述】:
我有一个 OpenGL ES 2.0 应用程序。在其中,我有一个类,它包含另一个类型的对象的数组,就像这样(这个问题被简化了):
public class StoreList(){
thisList StoreItems[];
public StoreList(int nuberOfItems){
thisList = StoreItems[numberOfItems];
}
}
最初,我填充列表,然后在应用程序期间的某些时间点(当用户在“商店”场景中时),可以将新项目添加到列表中,例如,列表可以看起来像这样:
Before After inserting object 'Fish' into index 1
Index 0 - Dog Index 0 - Dog
Index 1 - Fox Index 1 - Fish
Index 2 - Bird Index 2 - Fox
Index 3 - Snake Index 3 - Bird
Index 4 - Snake
现在,由于各种原因,此列表被迭代。例如,用于渲染、更新其位置等。
我遇到的问题是,我的应用程序使用 2 个线程 - GL 渲染线程和 Main/UI 线程。
当用户执行某个操作时,UI 线程调用一个“insertObject”方法,该方法插入一个额外的项目,如上所述。然而,渲染线程很乐意做这件事,如果它在调用“insertObject”的同时渲染索引 1 处的对象,那么它就会开始导致问题(列表中的每个对象都有不同数量的 openGL 四边形来绘制并且要绘制的数字包含在对象本身的变量中),因此如果索引 1 处的原始对象有 5 个四边形,而新对象只有 4 个,那么它开始尝试绘制第 5 个四边形,我们得到所有问题的方式(例如索引超出范围)。
render 方法、updateLogic 方法和 onTouchEvent 方法都声明为同步,但我仍然遇到问题。
我不确定如何确保 this 对象(StoreList 的实例及其中的所有内容以及它的“thisList”数组)一次只能从一个线程更新。
我看到的与并发问题有关的问题都是关于保护一个方法不被多个线程而不是对象调用,所以我有点困惑。
不胜感激。
【问题讨论】:
-
也许
CopyOnWriteArrayList更适合您? -
最简单的方法:通过
Lock保护列表。每个要读取或写入列表的方法都需要先获取Lock。稍微复杂一点:尝试使用@synchronized。只要在@synchronized(如wait())中没有使用阻塞结构,这应该可以完成工作。 -
感谢@Turing85,您的意思是在所有将读取/写入列表的代码上使用同步块吗? (使用列表本身作为锁定对象?)我只是想知道我是否可以简单地将读取/写入列表的任何方法声明为同步?我刚刚做到了,到目前为止没有崩溃(经过大约 30 次测试)。另外我不确定你的意思是'@synchronized'。你能举个例子吗?感谢您的帮助。
-
我不知道 CopyOnWriteArrayList @RealSkeptic,很有趣!
标签: java concurrency thread-safety race-condition synchronized