2012-08-10 60 views
4

爲什麼兩個同步塊不能由Java中的兩個不同線程同時執行。在Java中執行兩個同步塊

編輯

public class JavaApplication4 { 

    public static void main(String[] args) { 
     new JavaApplication4(); 
    } 

    public JavaApplication4() { 
     Thread t1 = new Thread() { 

      @Override 
      public void run() { 
       if (Thread.currentThread().getName().equals("Thread-1")) { 
        test(Thread.currentThread().getName()); 
       } else { 
        test1(Thread.currentThread().getName()); 
       } 
      } 
     }; 
     Thread t2 = new Thread(t1); 
     t2.start(); 
     t1.start(); 

    } 

    public synchronized void test(String msg) { 
     for (int i = 0; i < 10; i++) { 
      try { 
       Thread.sleep(100); 
      } catch (InterruptedException ex) { 
      } 
      System.out.println(msg); 
     } 
    } 

    public synchronized void test1(String msg) { 
     for (int i = 0; i < 10; i++) { 
      try { 
       Thread.sleep(100); 
      } catch (InterruptedException ex) { 
      } 
      System.out.println(msg + " from test1"); 
     } 
    } 
} 
+4

如果它們在不同的對象上同步,它們可以。如果它們在同一個對象上同步,那麼同時執行就會失敗目的。 – Keppil 2012-08-10 11:46:56

+0

我懷疑你有更深的擔憂。你能改說你的問題嗎? – 2012-08-10 11:50:40

+0

@Keppil請檢查EDIT部分 – 2012-08-10 11:51:18

回答

3

這就是整個同步的概念,如果你對對象(或類)進行鎖定,其他線程都不能訪問任何同步塊。

Class A{ 

public void method1() 
{ 
synchronized(this)//Block 1 taking lock on Object 
{ 
    //do something 
} 
} 

public void method2() 
{ 
synchronized(this)//Block 2 taking lock on Object 
{ 
    //do something 
} 
} 
} 

如果對象的一個​​線程進入任何同步塊,所有其他線程相同的對象的將必須等待線程出來的同步塊的輸入任何同步塊。如果有N個這樣的塊,則對象中只有一個線程一次只能訪問一個塊。請注意我的重點是同一個對象的線程。如果我們正在處理來自不同對象的線程,這個概念將不適用。

我還要補充一點,如果你對採取鎖定,上述概念將擴展到該類的任何對象。因此,如果不是說synchronized(this),我會使用synchronized(A.class),代碼將指示JVM,即與線程所屬的對象無關,使其等待其他線程完成同步的塊執行。

編輯:請理解,當你正在進行鎖定(通過使用同步關鍵字),你不只是鎖定一個塊。你正在鎖定對象。這意味着你是在告訴JVM:「嘿,這個線程做一些關鍵工作這可能會改變對象(或類)的狀態,所以不要讓任何其他線程做任何其他重要工作」。關鍵工作,這裏指的是同步塊中的所有代碼,它們鎖定該特定對象(或類),而不僅僅在一個同步塊中。

+0

但同步塊是完全獨立的。爲什麼它會被阻止。 – 2012-08-10 11:56:19

+0

你需要了解這個 - 你不是在塊上採取鎖,你是在對象(或類)採取鎖 – Kamal 2012-08-10 11:57:34

11

你的說法是錯誤的。只要它們不爭用相同的鎖,任何數量的同步塊都可以並行執行。

但是如果你的問題是關於爭奪相同鎖的塊,那麼問「爲什麼如此」是錯誤的,因爲這是整個概念的目的。程序員需要互斥機制,他們從Java通過​​得到它。

最後,您可能會問「爲什麼我們需要將代碼段並行排除在外」。答案是,有許多數據結構只有在以某種方式組織時纔有意義,並且當線程更新結構時,它必然會一部分完成,因此結構處於「斷開」狀態而它正在更新。如果另一個線程在這一點上出現並嘗試讀取結構,或者更糟糕的是,自行更新它,整個事情就會崩潰。

編輯

我看到你的榜樣,您的意見,現在很明顯是什麼困擾着你:​​修改的方法的語義。這意味着該方法將對this的顯示器進行鎖定。同一對象的所有​​方法將爭用相同的鎖。

+0

可以推理http://pastebin.com/tcJT009i – 2012-08-10 11:50:30

+0

的輸出這段代碼是一個相當可怕的惡夢。它檢查,它沒有明確設置和,差遠了線程的名字,使用一個線程實例作爲另一個線程的'Runnable'。我不敢預測會有什麼樣的後果。無論如何,我跑了它,它做了最明顯的事情:兩種方法相互排斥。 – 2012-08-10 11:53:43

+0

那只是一個虛擬的可怕代碼。但我的問題是,爲什麼爲t互斥的,當我沒有發現任何錯誤在裏面。兩個不同的線程正在訪問兩個不同的同步塊 – 2012-08-10 11:58:37

0

兩個線程可以同時執行同步塊,直到它們沒有鎖定同一個對象爲止。

如果塊在不同的對象上同步,它們可以同時執行。

synchronized(object1){ 
    ... 
} 

synchronized(object2){ 
    ... 
} 

編輯: Please reason the output for http://pastebin.com/tcJT009i

在當你調用鎖定在同一個對象獲得的同步方法的例子。嘗試創建兩個對象並查看。

0

這不是絕對正確的。如果你正在處理不同對象上的鎖,那麼多個線程可以執行這些塊。

synchronized(obj1){ 
     //your code here 
    } 

    synchronized(obj2){ 
     //your code here 
    } 

在上述情況下,一個線程可以執行第一和第二可以執行第二塊,所述點是這裏線程與不同的鎖工作。

你的說法是正確的,如果線程處理相同lock。每對象只有一個用Java鎖有關,如果一個線程獲取鎖定並執行然後其他線程必須等待,直到第一個線程釋放該lock .Lock能通過​​塊或方法獲得。