簡體   English   中英

從兩個不同的線程訪問相同的變量

[英]Accessing same variable from two different threads

我知道多線程的工作原理,如何使用同步的方法/塊-但是我在網上找不到一件事,對我來說還不清楚。

假設我們有:

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上的魔法值和對線程2上的生命值進行操作嗎? 這樣,我不會碰到相同的變量,但是我仍然在兩個不同的線程上使用'child'-因此它可能是不安全的。 使用“子級”時是否還應該同步?

編輯-一個例子;

gameloop.player_me.setX(5);
gameloop.player_me.setY(5);

我正在從兩個線程更改X和Y-顯然setX && setY是同步的。 但我也accesing在其他變量gameloop從第三個線程。 我應該在gameloop同步嗎?

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;
    }
  }
}

顯而易見,如果我想從兩個不同的線程訪問運行狀況,則需要進行如下的getter操作:

不,這不是顯而易見的。 如果您擔心線程安全,那么您的字段不應公開。 實際上,即使您不關心線程安全,也不應將它們公開。 而且,如果它們是私有的,則照原樣,您的Child類實際上是不可變的,因為沒有方法可以修改任何字段,因此不需要同步。

這樣,我不會碰到相同的變量,但是我仍然在兩個不同的線程上使用'child'-因此它可能是不安全的。 使用“子級”時是否還應該同步?

這取決於。 這兩個變量是否相互關聯? 還是應該始終保持一致狀態? 您的方法會修改狀態嗎?

假設Child類是可變的,如果兩個字段都完全不相關,則在修改每個字段時都不需要使用相同的鎖。 如果它們相關並且應該保持一致狀態,則需要使用相同的鎖來訪問它們。

每個細節都很重要。 如果我們只知道一個類有兩個字段,就不可能給出明確的答案。

例如,以您的最后一個示例為例,您可能一開始就不應使用setX()setY()方法。 您應該有一個setCoordinates(Coordinates c)方法和一個Coordinates getCoordinates()方法,它們將被同步。 這保證了x和y一起被原子地修改,並且沒有線程會看到新的X而不看到新的Y。 因此認為玩家處於原本不應該去的地方。 封裝是關鍵。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM