2013-02-11 107 views
1

我對於同步塊有疑問。執行下面的代碼後I M geeting輸出爲:線程:同步塊

Inside run=>thread 2 
Inside run=>thread 1 
Inside run=>thread 1 
Inside run=>thread 2 
Inside run=>thread 2 
Inside run=>thread 1 
Inside run=>thread 2 
Inside run=>thread 1 
Inside run=>thread 1 
Inside run=>thread 2 

我期待輸出只有一個線程將首先執行同步塊,然後只第二線程將得到synchornized塊的訪問。 可能是我理解錯誤的概念?

package com.blt; 

    public class ThreadExample implements Runnable { 
     public static void main(String args[]) 
     { 


      System.out.println("A"); 
      Thread T=new Thread(new ThreadExample()); 
      Thread T1=new Thread(new ThreadExample()); 
      System.out.println("B"); 
      T.setName("thread 1"); 
      T1.setName("thread 2"); 
      System.out.println("C"); 
      T.start(); 
      System.out.println("D"); 
      T1.start(); 
     } 


    synchronized public void run() 
    { 
     for(int i=0; i<5; i++) 
     { 
      try 
      { 
      System.out.println("Inside run=>"+Thread.currentThread().getName()); 
      Thread.currentThread().sleep(2000); 
      } 
      catch(InterruptedException e) 
      { 
       e.printStackTrace(); 
      } 
      } 
    } 
    } 
+0

嘗試僅實例化一個ThreadExample,並將同一實例傳遞給線程T和線程T1的構造函數,原因是人們已經提供了答案中所述的原因。 – Alderath 2013-02-11 10:18:17

回答

4

您的每個線程正在同步不同的對象。所以是的,他們不會互相鎖定。但更重要的是,run方法定義爲Runnable接口沒有一個同步修改器,你不應該添加一個(如你已經看到的,它沒有你認爲會的效果)。

要記住的關鍵一點是,當你使用synchronized修飾符的一個方法:

public synchronized void someMethod(); 

它實際上是一回事使用synchronized(this)。在這兩種情況下,您都鎖定了對象監視器。如果您有多個對象,則有多個顯示器。

以下是您自己的示例的修改版本,它可以按照您的預期工作。它使用一個共同的目標監視器(在這種情況下,你的類本身),使同步按預期工作:

public class ThreadExample implements Runnable { 
    public static void main(String args[]) { 
     System.out.println("A"); 
     Thread T = new Thread(new ThreadExample()); 
     Thread T1 = new Thread(new ThreadExample()); 
     System.out.println("B"); 
     T.setName("thread 1"); 
     T1.setName("thread 2"); 
     System.out.println("C"); 
     T.start(); 
     System.out.println("D"); 
     T1.start(); 
    } 

    public void run() { 
     synchronized (ThreadExample.class) { 
      for (int i = 0; i < 5; i++) { 
       try { 
        System.out.println("Inside run=>" 
          + Thread.currentThread().getName()); 
        Thread.sleep(500); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 
1

您已經創建的ThreadExample兩個Object,所以每個線程都有不同​​方法。

創建一個單一的目標和基準傳遞給線程,你會看到同步的效果。:)

ThreadExample thex = new ThreadExample(); 
Thread T=new Thread(thex); 
Thread T1=new Thread(thex); 

這裏既有線將使用同樣的方法​​。

3

你的問題是,如果同一塊顯示器上沒有鎖定,那麼2個同步塊不是互斥的。

記住this監視器上的同步方法鎖 - 你的代碼就相當於:

public void run() { 
    synchronized(this) { 
     //your code here 
    } 
} 

既然你創建的ThreadExample兩個實例他們每個人都有一個獨特的this

您可以通過使用兩個線程同一把鎖,例如解決您的問題:

public void run() { 
    synchronized(ThreadExample.class) { 
     //your code here 
    } 
} 

,甚至更好,通過Quoi創建ThreadExample只有一個實例,如指出。

0

呃,你正在同步每個線程的運行方法。 Thread1不會嘗試運行Thread2的運行方法,反之亦然。這就是爲什麼它與完全不同步的效果相同。

0

您正在創建類的兩個實例,並且您正在同步類,因此它們將獨立運行,因爲沒有通用鎖。他們將繼續分開運行。