【发布时间】:2021-07-06 18:42:27
【问题描述】:
我基本上有一个对象,它存储具有附加属性(如速度)的项目的 3D 位置。该位置由一个单独的线程每 100 毫秒计算一次。另一个线程访问这些属性并修改其中的一些。
模拟线程
// ...
double z = location.getZ();
// calculate new position
location.setZ(z);
// ...
其他话题
// ...
while(location.getZ() > 10); // Some busy waiting for demonstration
location.setSpeed(10);
// ...
我的第一个想法是对每个属性简单地使用volatile,但据我所知,对 volatile 属性的每个操作都必须是原子的。由于允许两个线程在某些情况下更改某些属性(例如速度),因此这似乎不起作用。
我的下一个想法是使用 java 的 synchronized 关键字并同步每个 getter 和 setter 结束整个模拟周期。
// Location.java
public synchronized double getZ() { /* ... */ }
// Simulation loop
synchronized(location) {
// calculations are done here
}
现在我想知道这是正确的方法还是有更好的方法。
可以在synchronized 块内调用getZ() 还是在内部这个结果需要单独的锁?
【问题讨论】:
-
1.当 2 个不同的线程根据某些规则改变一个共享结构时的架构似乎有点奇怪和危险。您可能会同时获得数据竞争和竞争条件。我建议三思而后行,例如,也许可以使用一些队列重新设计此解决方案。 2. 但是如果你坚持... :) 我会在位置结构中添加一个 java.util.concurrent.locks.ReentrantReadWriteLock 并使用锁来进行一致的读写而不是同步块。获取锁,读取/修改必填字段,释放锁。
-
为什么位置有“速度”属性?我同意 Anatoly G 的观点;同步只能解决底层问题,并不能解决你设计的逻辑问题。
标签: java concurrency synchronization