2017-11-06 10 views
0

2つのスレッドと2つのメソッドを持つ1つのオブジェクトがあるとします。 スレッド1はmethod1を使用します。 スレッド1で使用されているmethod1はまだを実行していますが、スレッド2ではmethod2を使用できますか?異なるスレッドが同じオブジェクトの異なる独立したメソッドに同時にアクセスできますか?

このすべては、オブジェクトがマルチスレッド化を念頭に置いて作成されたものではないことを前提としています(同期化も似ていなくても)、メソッドは同じ変数にアクセスしません。

このコードは、それが可能であることを示唆している:here

から

import java.io.IOException; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

public class multithreadaccess { 

    /** 
    * @param args 
    *   the command line arguments 
    */ 
    public static void main(String[] args) throws IOException { 
     TestClass tc = new TestClass(); 

     // invokes not sync method 
     FirstThreadRunnable ftr = new FirstThreadRunnable(tc); 
     Thread t1 = new Thread(ftr); 

     // invokes the sync method 
     SecondThreadRunnable str = new SecondThreadRunnable(tc); 
     Thread t2 = new Thread(str); 

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

     System.in.read(); 
    } 


    public static class TestClass { 

     private int callCount = 0; 

     public void secondmethod() { 
      System.out.println("second method activated! Call number:" + " [" + callCount++ + "] from thread: " 
        + Thread.currentThread().getId()); 
     } 

     public void firstmethod() throws InterruptedException { 
      // Test with the sleep 
      System.out.println("starting first slow method from thread: " + Thread.currentThread().getId()); 
      Thread.sleep(1000); // hold the monitor for 5sec 
      System.out.println("stopping first slow method! Call number:" + " [" + callCount++ + "] from thread: " 
        + Thread.currentThread().getId()); 

      // Test with spinning 
      /* 
      * System.out.println("MAKE IT SPIN! from thread: " + 
      * Thread.currentThread().getId()); boolean spin = true; 
      * while(spin){ 
      * 
      * } System.out.println("IT STOPPED SPINNING! from thread: " + 
      * Thread.currentThread().getId()); } 
      */ 
     } 
    } 

     // invokes the not sync method 
     public static class FirstThreadRunnable implements Runnable { 
      TestClass tester = null; 

      public FirstThreadRunnable(TestClass tester) { 
       this.tester = tester; 
      } 

      @Override 
      public void run() { 
       try { 
        tester.firstmethod(); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 

      } 
     } 

     // invokes the sync method 
     public static class SecondThreadRunnable implements Runnable { 

      TestClass tester = null; 

      public SecondThreadRunnable(TestClass tester) { 
       this.tester = tester; 
      } 

      @Override 
      public void run() { 
       tester.secondmethod(); 
      } 
     } 
    } 

変更されたコードでも、私はこれが可能であるかを理解していません。私はいつもオブジェクトが線形コードだと考えていました。しかし、これは、linearはメソッド内のコードだけであることを示唆しています(変数が複数のメソッドで使用されていない限り)。

答えて

3

あなたのコードの問題は、firstmethodsecondmethodは両方ともcallCount++なので、あなたが思ったように「独立」ではありません。

これは、両方のスレッドがその変数を更新しているため、race conditionを作成することがあります。あなたはintの代わりにAtomicIntegerを使用する必要があり、その後コードが動作します。

編集: 一般に、同期メカニズム(「自動ブロック」)は、高価でプログラムが遅くなるため、デフォルトでは有効になっていません。そのため、Javaは​​キーワードとスレッドセーフなクラスのようなものを提供し、共有変数とクリティカルセクションへの適切なアクセスを保証するためにAtomicIntegerを持っています。

+0

実際に共有変数があり、これが競合状態を引き起こす可能性がありますが、これはコードが(callCountの状況を除いて)最初のメソッドを呼び出し、2番目のメソッドを開始して終了し、最初のメソッドを終了します。私はいつも何らかの自動ブロック(同じオブジェクトから別のメソッドが実行されている間はあるメソッドへのアクセスがない)があると思っていましたが、何もありませんでしたか?任意のスレッドが任意のオブジェクトの任意のメソッドをいつでも実行できることを意味しますか? – harbun

+0

@harbunいいえいいえあなたが書いたように「自動ブロック」はありません。これは正確に 'AtomicInteger'のようなクラスが存在する理由です。 – Will

+0

通常、ロックや' synchronized'キーワードで実装される「自動ブロック」は、これらの操作が高価でプログラムが遅くなるため、デフォルトではありません。 – Will

関連する問題