同步塊的參數對象是塊鎖定的對象。 因此所有同步塊與同一對象排除彼此(和同一對象的所有同步方法)同時執行。
所以,如果你有這樣的例子
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,在類ExampleA
和ExampleB
),和我們有兩個鎖對象(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
可達),或一個只用於同步的特殊對象,並沒有改變。因爲所有相同的字符串文字都是相同的對象(即會排除對方的同步塊),而相同的非文字字符串(例如在運行時創建的字符串),因爲字符串對象通常是同步鎖定的不好的選擇)不是同一個對象,因此不會通過其他此類對象或文字排除同步塊,這往往導致微妙的錯誤。
您能否澄清一下您的問題? – reef 2011-02-25 16:54:14
同步塊的要點是線程安全地訪問多線程環境中的易失性字段。本教程可能會有幫助:http://www.csc.villanova.edu/~mdamian/threads/javamonitors.html – 2011-02-25 16:57:50
@reef先生爲什麼以前有一些答案現在被刪除... – satheesh 2011-02-25 17:21:21