top
Loading...
Java走下神壇之同步代碼等同于斷面
同步經常作為斷面被引用。斷面是指一次只能有一個線程執行它。多個線程同時執行同步代碼是有可能的。

這個誤解是因為很多程序員認為同步關鍵字鎖住了它所包圍的代碼。但是實際情況不是這樣的。同步加鎖的是對象,而不是代碼。因此,如果你的類中有一個同步方法,這個方法可以被兩個不同的線程同時執行,只要每個線程自己創建一個的該類的實例即可。



參考下面的代碼:

class Foo extends Thread
{
private int val;
public Foo(int v)
{
val = v;
}
public synchronized void printVal(int v)
{
while(true)
System.out.println(v);
}
public void run()
{
printVal(val);
}
}
class SyncTest
{
public static void main(String args[])
{
Foo f1 = new Foo(1);
f1.start();
Foo f2 = new Foo(3);
f2.start();
}
}

運行SyncTest產生的輸出是1和3交叉的。如果printVal是斷面,你看到的輸出只能是1或者只能是3而不能是兩者同時出現。程序運行的結果證明兩個線程都在并發的執行printVal方法,即使該方法是同步的并且由于是一個無限循環而沒有終止。

要實現真正的斷面,你必須同步一個全局對象或者對類進行同步。下面的代碼給出了一個這樣的范例。

class Foo extends Thread
{
private int val;
public Foo(int v)
{
val = v;
}
public void printVal(int v)
{
synchronized(Foo.class) {
while(true)
System.out.println(v);
}
}
public void run()
{
printVal(val);
}
}

上面的類不再對個別的類實例同步而是對類進行同步。對于類Foo而言,它只有唯一的類定義,兩個線程在相同的鎖上同步,因此只有一個線程可以執行printVal方法。

這個代碼也可以通過對公共對象加鎖。例如給Foo添加一個靜態成員。兩個方法都可以同步這個對象而達到線程安全。

作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗