我知道多线程是如何工作的,如何使用同步的方法/块 - 但是有一件事我无法在网上找到它并且对我来说并不清楚。
让我们说我们有:
public class Parent {
public Child child;
public Parent(){
child = new Child();
}
}
public class Child{
public int health;
public int mana;
public Child (){
health = 100;
mana = 100;
}
}
很明显,如果我想从两个不同的线程访问health
,我需要制作一个这样的getter:
public synchronized int getHealth(){return health;}
它是同一个变量,当我们从两个线程同时触摸它时 - 它可能会中断。 但对于整个孩子来说呢?'宾语?例如,我可以在线程1上的mana和线程2上的health上进行操作吗?通过这种方式,我不会触摸相同的变量,但我还在使用“孩子”这个变量。在两个不同的线程上 - 所以它可能是不安全的。 在使用' child'?
时,我是否也应该同步?gameloop.player_me.setX(5);
gameloop.player_me.setY(5);
我正在从两个线程中改变X和Y--很明显setX
&& setY
已同步。但是我也从第三个线程访问gameloop
中的其他变量。我应该在gameloop
上同步吗?
答案 0 :(得分:1)
synchronized
方法隐式锁定this
,所以不,两个线程不能同时获得生命值和法力值,因为同一个对象都被锁定。但是,您可以使用synchronized
语句为这两个锁定对象使用不同的锁定对象:
class Child {
private int health, mana;
private Object healthLock, manaLock;
public int getHealth() {
synchronized(healthLock) {
return health;
}
}
public int getMana() {
synchronized(manaLock) {
return mana;
}
}
}
答案 1 :(得分:-1)
很明显,如果我想从两个不同的线程访问健康状况,我需要制作一个这样的getter:
不,这不明显。如果您担心线程安全,那么您的字段不应该是公开的。实际上,即使您不关心线程安全,它们也不应该公开。如果它们是私有的,那么你的Child类实际上是不可变的,因为没有方法可以修改任何字段,所以不需要同步。
通过这种方式,我不会触摸相同的变量,但我还在使用“孩子”。在两个不同的线程上 - 所以它可能是不安全的。我应该在使用' child'?
时同步
这取决于。这两个变量是否相互关联?或者它们是否应始终保持一致状态?你的方法是否会修改状态?
假设Child类是可变的,如果两个字段完全不相关,则在修改每个字段时不需要使用相同的锁。如果它们是相关的并且应该保持一致状态,那么您需要使用相同的锁来访问它们。
每个细节都很重要。如果我们所知道的是一个班级有两个领域,那就不可能给出应该做什么的明确答案。
举个例子,你可能不应该首先使用setX()
和setY()
方法。您应该使用setCoordinates(Coordinates c)
方法和Coordinates getCoordinates()
方法进行同步。这保证了x和y一起被修改,原子化,并且没有线程将看到新的X而没有看到新的Y.因此认为玩家所在的位置应该永远不会存在。封装是关键。