java.util.concurrent包(1)——synchronized和lock

一、對synchronized的改進
JDK5後引入了線程併發庫java.util.concurrent。JSR 166小組花了這麼多時間來開發java.util.concurrent.lock框架呢?答案很簡單——synchronized同步是不錯,但它並不完美,有一些功能性的限制:無法中斷一個正在等候獲得鎖的線程,也無法通過投票得到鎖,如果不想等下去也就沒法得到鎖。同步還要求鎖的釋放只能在與獲得鎖所在的堆棧幀相同的堆棧幀中進行,多數情況下這沒問題,而且與異常處理交互得很好,但確實存在一些非塊結構的鎖定更合適的情況。


二、ReentrantLock類
java.util.concurrent.lock中的Lock框架是鎖定的一個抽象,它允許把鎖定的實現作爲Java類,而不是作爲語言的特性來實現。這就爲Lock的多種實現留下了空間,各種實現可能有不同的調度算法、性能特性或者鎖定語義。ReentrantLock類實現了Lock,它擁有與synchronized相同的併發性和內存語義,但是添加了類似鎖投票、定時鎖等候和可中斷鎖等候的一些特性。此外它還提供了在激烈爭用情況下更佳的性能,也就是說當許多線程都想訪問共享資源時,JVM可以花更少的時候來調度線程,把更多時間用在執行線程上。

Reentrant鎖意味着什麼呢?簡單來說它有一個與鎖相關的獲取計數器,如果擁有鎖的某個線程再次得到鎖,那麼獲取計數器就加1,然後鎖需要被釋放兩次才能獲得真正釋放。這模仿了synchronized的語義:如果線程進入由線程已經擁有的監控器保護的synchronized塊,就允許線程繼續進行,當線程退出第二個或者後續synchronized 塊時不釋放鎖,只有線程退出它進入的監控器保護的第一個synchronized塊時才釋放鎖。

lock必須在finally塊中釋放。否則如果受保護的代碼將拋出異常,鎖就有可能永遠得不到釋放,忘記在finally塊中釋放鎖非常麻煩。而使用synchronized同步,JVM將確保鎖會獲得自動釋放。


三、代碼對比
synchronized同步
public class SynchronizeOutput
{
public synchronizedvoid output(String name)
{
for (int i = 0; i < name.length(); i++)
{
System.out.print(name.charAt(i));
}
System.out.println();
}
}


public class SynchronizeTest
{
public static void main(String[] args)
{
final SynchronizeOutput synOutput = new SynchronizeOutput();


for (int i = 0; i < 100; i++)
{
new Thread(new Runnable() {
public void run()
{
synOutput.output("I am xy");
}
}).start();
}
}
}

Lock
public class LockOutput
{
Lock lock = new ReentrantLock();

public void output(String name)
{
lock.lock();
try
{
for (int i = 0; i < name.length(); i++)
{
System.out.print(name.charAt(i));
}
System.out.println();
}
finally
{
lock.unlock();
}
}
}

public class LockTest
{
public static void main(String[] args)
{
final LockOutput lockoutput = new LockOutput();
for (int i = 0; i < 100; i++)
{
new Thread(new Runnable() {
public void run()
{
lockoutput.output("I am xy");
}
}).start();
}
}

}

原帖地址:http://blog.csdn.net/fw0124/article/details/6672522


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章