2011-02-25 358 views
0

我明白一段代碼的同步意味着特定的代碼在某一時刻只能被一個線程訪問,即使很多線程正在等待訪問它。代碼塊上的同步

當我們在run方法中編寫線程類時,我們通過給出對​​象來啓動同步塊。 例如

class MyThread extends Thread{ 
    String sa; 
    public MyThread(String s){ 
     sa=s; 
    } 
    public void run(){ 
    synchronized(sa){ 
     if(sa.equals("notdone"){ 
      //do some thing on object 
     } 
    } 
    }  
} 

這裏我們給SA對象synchronized塊是什麼that.any我們將如何對代碼的特定塊

+2

您能否澄清一下您的問題? – reef 2011-02-25 16:54:14

+0

同步塊的要點是線程安全地訪問多線程環境中的易失性字段。本教程可能會有幫助:http://www.csc.villanova.edu/~mdamian/threads/javamonitors.html – 2011-02-25 16:57:50

+0

@reef先生爲什麼以前有一些答案現在被刪除... – satheesh 2011-02-25 17:21:21

回答

0

所有線程都在此對象同步提供同步的需要會等到當前線程完成其工作。例如,如果您對收集進行了讀/寫操作,那麼您希望進行同步。所以你可以在方法setget中寫同步塊。在這種情況下,如果一個線程正在讀取信息,那麼不是所有其他要讀取或寫入的線程都會等待。

+0

先生..我明白了什麼同步塊會做,但我沒有得到什麼是需要給對象的特定同步塊 – satheesh 2011-02-25 16:58:49

1

我建議

  • 延伸Runnable接口,而不是主題。
  • 不會在外部鎖定Runnable。相反,你應該調用一個可能使用內部鎖的方法。
  • 字符串不是一個很好的選擇作爲鎖。這意味着「嗨」和「嗨」將共享一個鎖,但新的字符串(「嗨」)不會。
  • 如果你鎖定線程的所有其他線程,爲什麼你使用多線程?
+0

..我得到了你的意思可能是我的代碼是不正確的與字符串對象的鎖。我問在正常的同步方法中,我們沒有給出任何對象。但是在同步塊中,我們正在給一個對象什麼需要呢? – satheesh 2011-02-25 17:10:20

+0

在一個複雜的對象中,您可以擁有多個鎖,並且您需要爲每個鎖創建一個同步塊。有時你不想鎖定'this',因爲它也可以鎖定在你的課外,所以你可以鎖定你提供的對象。一些線程安全的集合沒有線程安全的迭代器,所以你必須鎖定集合,只是爲了迭代(但沒有別的) – 2011-02-25 22:25:28

1

同步塊的參數對象是塊鎖定的對象。 因此所有同步塊與同一對象排除彼此(和同一對象的所有同步方法)同時執行。

所以,如果你有這樣的例子

class ExampleA extends Thread() { 

    public ExampleA(Object l) { 
     this.x = l; 
    } 

    private Object x; 

    public void run() { 
     synchronized(x) {  // <-- synchronized-block A 
      // do something 
     } 
    } 
} 
class ExampleB extends Thread() { 

    public ExampleB(Object l) { 
     this.x = l; 
    } 

    private Object x; 

    public void run() { 
     synchronized(x) {  // <-- synchronized-block B 
      // do something else 
     } 
    } 
} 

Object o1 = new Object(); 
Object o2 = new Object(); 

Thread eA1 = new ExampleA(o1); 
Thread eA2 = new ExampleA(o2); 
Thread eB1 = new ExampleB(o1); 
Thread eB2 = new ExampleB(o2); 

eA1.start(); eA2.start(); eB1.start(); eB2.start(); 

現在我們有兩個同步塊(A和B,在類ExampleAExampleB),和我們有兩個鎖對象(01和02)。

如果我們現在看的同時執行,我們可以看到:

  • A1可以並行執行A2和B2,而不是B1。
  • A2可以並行執行到A1和B1,但不能執行到B2。
  • B1可以與A2和B2並行執行,但不能與A1執行。
  • B2可以與A1和B1並行執行,但不能與A2執行。

因此,同步只取決於參數對象,而不是選擇同步塊。


在你的榜樣,您使用的是這樣的:

synchronized(sa){ 
    if(sa.equals("notdone"){ 
     //do some thing on object 
    } 
} 

這看起來像你儘量避免有人改變了你的實例變量sa到另一個字符串,而你是比較它和工作 - 但它不避免這一點。

同步不上一個變量工作,它工作在對象上 - 和有問題的對象通常應該是一些對象,它包含的變量(在你的情況下,當前MyThread對象,通過this可達),或一個只用於同步的特殊對象,並沒有改變。因爲所有相同的字符串文字都是相同的對象(即會排除對方的同步塊),而相同的非文字字符串(例如在運行時創建的字符串),因爲字符串對象通常是同步鎖定的不好的選擇)不是同一個對象,因此不會通過其他此類對象或文字排除同步塊,這往往導致微妙的錯誤。

0

所以問題是塊的同步對象的功能是什麼?

對象的所有實例都具有所謂的監視器。在正常執行中,該監視器是無主的。

希望進入同步塊的線程必須擁有對象監視器。但是,一次只能有一個線程擁有該顯示器。因此,如果監視器當前是無主的,則線程佔有並執行同步的代碼塊。該線程在離開同步塊時釋放監視器。

如果監視器當前擁有,則需要輸入同步塊的線程必須等待監視器被釋放,以便它可以獲得所有權並輸入該塊。多於一個線程可以等待,如果是,則只有一個線程會被賦予顯示器的所有權。其餘的將回到等待。