从两个不同的线程访问相同的变量

时间:2015-10-25 09:05:33

标签: java multithreading

我知道多线程是如何工作的,如何使用同步的方法/块 - 但是有一件事我无法在网上找到它并且对我来说并不清楚。

让我们说我们有:

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上同步吗?

2 个答案:

答案 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.因此认为玩家所在的位置应该永远不会存在。封装是关键。