Kotlin,竞赛条件问题

相关的代码在这里

本质上,我们有两个线程,一个是引导保持调用display()的渲染,另一个是关注用户输入,相应地调用相应的鼠标或键事件

对于相机和物体来说,视极和对象极点都不是帮助类的辅助类。

他们的方法都是从display()和用户输入方法中调用的。

当输入线程间接调用它们时, objectpole.calcMatrix()同时调用viewpole.calcMatrix()objectpole.calcMatrix() ,例如basicLighting.mouseDragged() – > objectpole.mouseDragged() – > rotateView() – > calcMatrix()

当我开始使用池对象来降低特定场景中的GC压力时,竞态条件开始出现。 我查了几十次,每个对象都只用了一次(除了用的when )。

我通过打印每个display()调用的视图矩阵来检测竞争状态。 只要不一样,就意味着我得到了一个。 这里是一个例子。

调查中,我发现使用简单的println ,例如, Viewpole.calcMatrix()有时在另一个调用完成之前得到调用,完全执行它。

在每个calcMatrix() (viewpole和objectpole)上添加@Synchronized减少了很多,我说80/90%。

但是,有时候,我还经历了种族的状况。 我试图synchronize(lock){}也来自用户输入线程的每个调用,如下所示:

 val lock = Any() override fun mousePressed(e: MouseEvent) { synchronized(lock) { viewPole.mousePressed(e) objectPole.mousePressed(e) } } 

它没有帮助。

我究竟做错了什么? 什么是正确的方式来实现我的情况下的同步? 也就是说,两个线程调用同一个类。

线程问题永远不会是调用同一类的线程。 这是关于共享线程之间的可变状态。 正如我所看到的,你的共享状态是矩阵。

你在做什么错误很难说,没有审查你的整个代码。 但是这里有一些提示:/ viewPole.calcMatrix()返回对mat4_B的引用。 在display()中,这个引用在synchronized块之外被使用。 因此,mat4_B可能会在display()/ viewPole.calcMatrix()和objectPole.calcMatrix()使用时同时被修改。 所以viewPole矩阵可能基于不同的状态,然后objectPole矩阵。 我不能说这是否是你的用例的问题。

方法应该是:尽可能地减少共享状态(即通过传递副本)/在单个原子(同步)操作中获取所有数据