synchronized關鍵字
- synchronized關鍵字修飾函數(shù)方法
使用synchronized關鍵字時,會獲取java對象的內置鎖,內置鎖會保護整個方法。
public synchronized void add(){
count++;
}
synchronized也可以修飾靜態(tài)方法,內置鎖會鎖住整改類。
- synchronized關鍵字修飾代碼塊
synchronized可以修飾代碼塊,只鎖住需要保護的代碼區(qū)域
public class SynchronizedThread {
public void add(){
synchronized(this)
{
count++;
}
}
}
synchronized是一種高開銷操作,實際應用不需要鎖住整個方法,可以使用同步代碼塊操作。
使用特殊域變量
使用volatile關鍵字修飾變量,沒有鎖同步開銷,每次使用變量時需要重新計算,不會直接使用寄存器的值,此變量不是原子操作,不可以修飾final對象。
public class SynchronizedThread{
private volatile int count= 0;
public void add(){
count++;
}
}
使用原子變量實現(xiàn)線程同步
在java的util.concurrent.atomic包中提供了創(chuàng)建了原子類型變量的工具類,使用該類可以簡化線程同步。
public class SynchronizedThread{
private AtomicInteger count= new AtomicInteger(0);
public void add(){
count.addAndGet(1);
}
}
原子操作適合線程簡單對象的計算。
使用重入鎖實現(xiàn)線程同步
在JavaSE5.0中新增了一個java.util.concurrent包來支持同步。ReentrantLock類是可重入、互斥、實現(xiàn)了Lock接口的鎖,它與使用synchronized方法和快具有相同的基本行為和語義,并且擴展了其能力。
public class SynchronizedThread{
private int count= 0;
private Lock lock = new ReentrantLock();
public void add(){
lock.lock();
try{
count++;
}finally{
lock.unlock();
}
}
}
使用try模塊語句,在finally模塊中釋放鎖,防止死鎖。
ReentrantLock類可以構造公平鎖,每個線程阻塞相同的時間,但由于能大幅度降低程序運行效率,不推薦使用。
使用局部變量實現(xiàn)線程同步
如果使用ThreadLocal管理變量,則每一個使用該變量的線程都獲得該變量的副本, 副本之間相互獨立,這樣每一個線程都可以隨意修改自己的變量副本,而不會對其他線程產生影響。
public class SynchronizedThread{
private static ThreadLocal<Integer> count= new ThreadLocal<Integer>(){
@Override
protected Integer initialValue(){
return 0;
}
};
public void add(){
count.set(count.get()+1);
}
}
使用阻塞隊列實現(xiàn)線程同步
前面5種同步方式都是在底層實現(xiàn)的線程同步,但是我們在實際開發(fā)當中,應當盡量遠離底層結構。 使用javaSE5.0版本中新增的java.util.concurrent包將有助于簡化開發(fā)。 本小節(jié)主要是使用LinkedBlockingQueue<E>來實現(xiàn)線程的同步。
public class BlockingSynchronizedThread {
private LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>();
private class LinkBlockThread implements Runnable {
@Override
public void run() {
try {
int n = queue.take();
System.out.println(n);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}