2016-04-27 10 views
0

メインスレッドと子スレッドの2つのスレッドが実行されています。彼らは活動は以下のとおりです。実行が非同期セクションにあるときにスレッドがブロックされた状態になる理由

  1. 子スレッドは100に1つの
  2. メインスレッドの合計をカウントし、それが子供で計算されます一度(私はwaitnotifyを使用)、総合計を出力します。また、子スレッドのステータスを出力します。

以下はコード部分です。

class MainThread { 
    public static void main(String[] args) throws InterruptedException { 
     ThreadB b = new ThreadB(); 
     b.setName("Child thread: "); 
     b.start(); 

     synchronized(b) { 
      System.out.print("\nwaiting for b to complete\n"); 

      b.wait(); 

      System.out.print("\nno more wait .........................\n"); 
      for (int i = 0; i < 1000; i++) 
       System.out.print("\n" + b.getName() + "'s state:" + b.getState()); 
     } 
     Thread.sleep(1000); 

     System.out.print("\n" + b.getName() + "state:" + b.getState()); 
     System.out.print("\ntotal in " + Thread.currentThread().getName() + "is :" + b.total); 
    } 
} 

class ThreadB extends Thread { 

    int total; 

    public void run() { 
     synchronized(this) { 
      for (int i = 0; i < 100; i++) 
       total += i; 
      System.out.println(this.getName() + "finished sum, lets notify other objects"); 

      notify(); 
      System.out.println(this.getName() + " done with notify and sync block\n"); 
     } 

     System.out.println(this.getName() + " : entered non critical section"); 
     for(int j = 0; j < 1000; j++) { 
      System.out.print("Hi "); 
     } 
    } 
} 
  1. 子は、その同期ブロックを終了し、メインスレッドに通知しました。それでも、ループ内に"Hi "という文字を印刷するだけの非同期部分が開始されています。
  2. 通知後メインスレッドが作業を再開し、子のステータスを表示します。

しかし、ここでは私の観察である:実行中"Hi "(非シンクブロックにあるforループ)、時には子供のステータスがRUNNABLE、それはBLOCKEDだ倍の大半です。たとえば、次のようにその非同期ブロックを実行するときに、子スレッドがBLOCKED状態で進入させ何

Child thread: 's state:RUNNABLE Hi Hi Hi 

Child thread: 's state:BLOCKED Hi Hi Hi Hi  

答えて

-1

時にはThreadBメインスレッドより速く実行され、最初に同期化されます。この場合、あなたのシナリオで動作するはずです。しかし、時にはメインスレッドがsynchronized(b)で高速に実行されることがあります。 ThreadBはメインスレッドによってブロックされ、そのスレッドは次にbからの通知を待ちます。 同期スレッドをメインスレッドから削除して、b.wait()でのみリレーを実行してください。

+0

これは間違いありません。 b.wait()は待機中にモニターをあきらめています。したがって、デッドロックは発生しません。 – rpy

4

2つのスレッドは同じデバイスに同時に印刷できません。彼らが試してみると、そのうちの1つがブロックされなければなりません。

+0

しかし、私は両方のSOPステートメント(非csと "HI"印刷)をコメントしても、私はまだ子スレッドの状態がほとんどの時間 "ブロック"されていることを観察した。つまり、コードの非同期部分の印刷ステートメントを100回繰り返しただけのループもブロックされました –

+1

私たちが見ることのできないコードにコメントするのは難しいです。コードは実際に何をしていましたか? 100まで数えて何もしないループは、瞬間的になり、おそらく最適化されます。おそらく、ガーベジコレクション、メモリ割り当て、または他の何十もののいずれかが、同期化されたものに衝突する可能性があります。 –

+0

ありがとうございました...私はあなたのポイントを理解しました –

0

2つのスレッドは、スレッドBではお互いに同期しませんが、 Printstreamのwriteメソッド(同期ブロックを持つため、一度に1つのスレッドだけがストリームに書き込むことができます)。

public void write(int b) { 
    try { 
     synchronized (this) { 
      ensureOpen(); 
      out.write(b); 
      if ((b == '\n') && autoFlush) 
       out.flush(); 
     } 
    } 
+0

しかし、私は両方のSOPステートメント(非csと "HI"印刷)をコメントしたとしても、私はまだ子スレッドの状態がほとんどの時間 "ブロック"を観察した。つまり、コードの非同期部分の印刷ステートメントを100回繰り返しただけのループもブロックされました。 –

0

私はあなたの質問を完全に理解していません。子スレッドがハングすると言っていますか?? (つまり、あなたはそれが永遠にブロックされると言っていますか?)もしそうなら、おそらくの通知が失われたです。

プログラムにはデータ競争が含まれています。メインスレッドがb.start()を呼び出した後、2つのスレッドは新しいThreadBオブジェクトで同期を競う。 ThreadBスレッドがレースに勝った場合、同期ブロックに入り、100までカウントし、this.notify()にコールして終了します。

はできるだけ早くThreadBスレッドが​​ブロックを出るときに、その後、MainThreadスレッドがその​​ブロックを入力し、b.wait()を呼び出すことができます。b.notify()と呼ばれる他のスレッドがないため、b.wait()呼び出しは返されません。ThreadBスレッドはすでに完了しており、その時点で終了しています。

b.notify()へのコールは、すでに待機中の他のスレッドがない場合は、となります。何でもありません。オブジェクトbは通知されたことを覚えていません。


wait()notify()方法は、非常に特定の方法で使用されることを意図した低レベルプリミティブです。詳細は、Guarded Blocks Tutorialを参照してください。

+0

これまで完全にブロックされていません。終了すると、forループスレッドは終了します。私の唯一の懸念は、このforループ実行中、スレッド状態がBlockedとして出力されていることです。 –

関連する問題