相关代码here
基本上,我们有两个线程,一个引导持续调用display()
的渲染,另一个负责用户输入,相应地调用相应的mouse or key event
Viewpole和object极点不是辅助类,以促进关于相机和对象的矩阵处理。
他们的方法都是从display()
和用户输入方法调用的。
display()
会调用viewpole.calcMatrix()
和objectpole.calcMatrix()
,例如basicLighting.mouseDragged()
- > objectpole.mouseDragged()
- > rotateView()
- > calcMatrix()
当我开始使用pool objects来降低特定情况下的GC压力时,竞争条件开始出现。我检查了几十次,每个对象只使用一次(when
除外)。
我通过打印view matrix每个display()
来电来检测竞争状况。每当它与众不同时,就意味着我得到了一个。示例here。
调查,我发现使用简单的println
,例如,Viewpole.calcMatrix()
有时在另一个调用完成之前被调用以完全执行它。
在每个@Synchronized
(viewpole和objectpole)上添加calcMatrix()
减少了很多,我说80/90%。
但是,有时候,我会遇到竞争状况。我也尝试synchronize(lock){}
来自用户输入线程的每个调用,例如here:
val lock = Any()
override fun mousePressed(e: MouseEvent) {
synchronized(lock) {
viewPole.mousePressed(e)
objectPole.mousePressed(e)
}
}
它没有帮助。
我做错了什么?那么为我的案例实现同步的正确方法是什么?也就是说,两个线程调用同一个类。
答案 0 :(得分:1)
线程问题绝不是关于调用相同类的线程。它是关于在线程之间共享可变状态。 我可以看到,你的共享状态就是矩阵。
如果不审查整个代码,很难说你做错了什么。但这里有一些提示: / viewPole.calcMatrix()返回对mat4_B的引用。 在display()中,此引用随后在synchronized块之外使用。因此mat4_B可能会在display()使用时同时修改 / viewPole.calcMatrix()和objectPole.calcMatrix()在单独的同步块中调用。因此viewPole矩阵可能基于与objectPole矩阵不同的状态。我不知道这是否是您的用例的问题。
方法应该是: /尽可能减少共享状态(即通过传递副本) /在单个原子(同步)操作中获取所有数据