1、對synchronized的改進
JDK5後引入了線程併發庫java.util.concurrent。JSR 166小組花了這麼多時間來開發java.util.concurrent.lock框架呢?答案很簡單——synchronized同步是不錯,但它並不完美,有一些功能性的限制:沒法中斷一個正在等候得到鎖的線程,也沒法經過投票獲得鎖,若是不想等下去也就無法獲得鎖。同步還要求鎖的釋放只能在與得到鎖所在的堆棧幀相同的堆棧幀中進行,多數狀況下這沒問題,並且與異常處理交互得很好,但確實存在一些非塊結構的鎖定更合適的狀況。
2、ReentrantLock類
java.util.concurrent.lock中的Lock框架是鎖定的一個抽象,它容許把鎖定的實現做爲Java類,而不是做爲語言的特性來實現。這就爲Lock的多種實現留下了空間,各類實現可能有不一樣的調度算法、性能特性或者鎖定語義。ReentrantLock類實現了Lock,它擁有與synchronized相同的併發性和內存語義,可是添加了相似鎖投票、定時鎖等候和可中斷鎖等候的一些特性。此外它還提供了在激烈爭用狀況下更佳的性能,也就是說當許多線程都想訪問共享資源時,JVM能夠花更少的時候來調度線程,把更多時間用在執行線程上。
Reentrant鎖意味着什麼呢?簡單來講它有一個與鎖相關的獲取計數器,若是擁有鎖的某個線程再次獲得鎖,那麼獲取計數器就加1,而後鎖須要被釋放兩次才能得到真正釋放。這模仿了synchronized的語義:若是線程進入由線程已經擁有的監控器保護的synchronized塊,就容許線程繼續進行,當線程退出第二個或者後續synchronized 塊時不釋放鎖,只有線程退出它進入的監控器保護的第一個synchronized塊時才釋放鎖。
lock必須在finally塊中釋放。不然若是受保護的代碼將拋出異常,鎖就有可能永遠得不到釋放,忘記在finally塊中釋放鎖很是麻煩。而使用synchronized同步,JVM將確保鎖會得到自動釋放。
3、代碼對比
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();
}
}
java
}算法
原帖地址:http://blog.csdn.net/fw0124/article/details/6672522多線程