web-dev-qa-db-ja.com

複数の異なるスレッド間で変数を共有する

このように複数のスレッド間で変数を共有したい:

boolean flag = true;
T1 main = new T1();
T2 help = new T2();
main.start();
help.start();

メインスレッドとヘルプスレッド間でflagを共有したいのですが、これらは2つの異なるJava私が作成したクラスです。これを行う方法はありますか?ありがとう!

17
user1031431

どちらも T1およびT2は、この変数を含むクラスを参照できます。
その後、この変数volatileを作成できます。これは、
その変数への変更は、両方のスレッドですぐに表示されます。

詳しくは この記事 をご覧ください。

揮発性変数は同期の可視性機能を共有しますが、原子性機能は共有しません。つまり、スレッドは自動的に揮発性変数の最新の値を参照します。これらはスレッドセーフティを提供するために使用できますが、非常に限られた場合にのみ使用できます。複数の変数間または変数の現在値とその将来値の間に制約を課さない場合のみです。

また、volatileを使用することと状態を共有するより複雑な手段を使用することの長所/短所に注意してください。

28
Brian Agnew

他の提案に加えて、コントロールクラスでフラグをラップし、親クラスでフラグの最終インスタンスを作成することもできます。

public class Test {
  class Control {
    public volatile boolean flag = false;
  }
  final Control control = new Control();

  class T1 implements Runnable {
    @Override
    public void run() {
      while ( !control.flag ) {

      }
    }
  }

  class T2 implements Runnable {
    @Override
    public void run() {
      while ( !control.flag ) {

      }
    }
  }

  private void test() {
    T1 main = new T1();
    T2 help = new T2();

    new Thread(main).start();
    new Thread(help).start();
  }

  public static void main(String[] args) throws InterruptedException {
    try {
      Test test = new Test();
      test.test();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
15
OldCurmudgeon

T1T2のインスタンス間で可視化するには、2つのクラスに変数を含むオブジェクトへの参照を含めることができます。

スレッドの実行中に変数を変更する場合は、同期を考慮する必要があります。最適なアプローチは要件に応じて異なりますが、主なオプションは次のとおりです。

  • 変数をvolatile;にします。
  • AtomicBoolean ;に変換します。
  • それを使用するコードの周りで本格的な同期を使用します。
5
NPE

staticを使用しても問題は解決しません。

synchronizeを使用すると、変数が別のスレッドで使用されているときにロックされます。

volatileキーワードを使用して、すべてのスレッド間で変数を更新し続ける必要があります。

Volatileを使用することは、クラスをスレッドセーフにする別の方法(同期、アトミックラッパーなど)です。スレッドセーフとは、メソッドまたはクラスインスタンスを問題なく複数のスレッドで同時に使用できることを意味します。

4
Bugs Buggy
  1. 静的にすることで、この問題を解決できます。
  2. 他のスレッドのメインスレッドへの参照とその変数の可視化
4
Romczyk

ロック変数「a」と「b」を使用し、「クリティカルセクション」を逆順にロックするためにそれらを同期できます。例えば。 「a」に通知してから「b」、「PRINT」をロックし、「b」に通知してから「a」をロックします。

以下のコードを参照してください:-

public class EvenOdd {

static int a = 0;

public static void main(String[] args) {

    EvenOdd eo = new EvenOdd();

    A aobj = eo.new A();
    B bobj = eo.new B();

    aobj.a = Lock.lock1;
    aobj.b = Lock.lock2;

    bobj.a = Lock.lock2;
    bobj.b = Lock.lock1;

    Thread t1 = new Thread(aobj);
    Thread t2 = new Thread(bobj);

    t1.start();
    t2.start();

}

static class Lock {
    final static Object lock1 = new Object();
    final static Object lock2 = new Object();
}

class A implements Runnable {

    Object a;
    Object b;

    public void run() {
        while (EvenOdd.a < 10) {
            try {
                System.out.println(++EvenOdd.a + " A ");
                synchronized (a) {
                    a.notify();
                }
                synchronized (b) {
                    b.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

class B implements Runnable {

    Object a;
    Object b;

    public void run() {
        while (EvenOdd.a < 10) {

            try {
                synchronized (b) {
                    b.wait();
                    System.out.println(++EvenOdd.a + " B ");
                }
                synchronized (a) {
                    a.notify();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

}

出力:-1 A 2 B 3 A 4 B 5 A 6 B 7 A 8 B 9 A 10 B

0