【问题标题】:Accessing same variable from two different threads从两个不同的线程访问相同的变量
【发布时间】:2015-10-25 09:05:32
【问题描述】:

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

假设我们有:

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

【问题讨论】:

  • 当你 同步方法时,你实际上是在同步对变量的访问,因为方法返回变量......你能发布多线程代码......
  • 您在网络上的任何地方都找不到答案?这让我很惊讶。你试过Java Language Specification吗?
  • aww,这实际上是一个很棒的网站 O.o。谢谢。
  • “Getter”是一种设计模式。它不是 Java 语言的一部分。调用 getter 来访问某个对象中的某个字段与访问同一字段的任何其他方法没有不同的含义。

标签: java multithreading


【解决方案1】:

synchronized 方法 隐式锁定this,所以不,两个线程不能同时获得生命值和法力值,因为同一个对象都被锁定了。但是,您可以通过使用 synchronized statement 为它们使用不同的锁定对象:

class Child {
  private int health, mana;
  private Object healthLock, manaLock;

  public int getHealth() {
    synchronized(healthLock) {
      return health;
    }
  }

  public int getMana() {
    synchronized(manaLock) {
      return mana;
    }
  }
}

【讨论】:

    【解决方案2】:

    这很明显,如果我想从两个不同的线程访问健康,我需要像这样制作一个 getter:

    不,这并不明显。如果您担心线程安全,那么您的字段不应该是公开的。事实上,它们不应该公开,即使您不关心线程安全。如果它们是私有的,那么您的 Child 类实际上是不可变的,因为没有方法可以修改任何字段,因此不需要同步。

    通过这种方式,我不会触及同一个变量,但我仍然在两个不同的线程上使用 'child' - 所以它可能不安全。使用“child”时我是否也应该同步?

    这取决于。这两个变量是否相互关联?或者它们应该始终保持一致的状态?您的方法是否修改状态?

    假设 Child 类是可变的,如果两个字段完全不相关,则在修改它们时不需要使用相同的锁。如果它们是相关的并且应该保持一致的状态,那么您需要使用相同的锁来访问它们。

    每个细节都很重要。如果我们只知道一个类有两个字段,就不可能给出一个明确的答案。

    以您的最后一个示例为例,您可能一开始就不应该有 setX()setY() 方法。您应该有一个 setCoordinates(Coordinates c) 方法和一个 Coordinates getCoordinates() 方法,它们将被同步。这保证了 x 和 y 一起被原子地修改,并且任何线程都不会看到新的 X 而没有看到新的 Y。因此认为玩家处于一个不应该出现的位置。封装是关键。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-09
      相关资源
      最近更新 更多