monitor
同一monitor阻塞,不同monitor互斥
synchronized(鎖)
Java中每一個對象都可以作爲鎖,這是synchronized實現同步的基礎:
普通同步方法(實例方法),鎖是當前實例對象 ,進入同步代碼前要獲得當前實例的鎖
靜態同步方法,鎖是當前類的class對象 ,進入同步代碼前要獲得當前類對象的鎖
同步方法塊,鎖是括號裏面的對象,對給定對象加鎖,進入同步代碼庫前要獲得給定對象的鎖。
/**
* 對象鎖,代碼級別,同一對象爭用該鎖,this爲SynMethod實例,synchronized的鎖綁定在this對象上
*/
public void method1() {
synchronized (this) {
}
}
等於
/**
* 對象鎖,方法級別,同一對象爭用該鎖,普通(非靜態)方法,synchronized的鎖綁定在調用該方法的對象上,與上一個寫法含義一致
*/
public synchronized void method2() {
}
等於
/**
* 類鎖,代碼級別,同一類爭用該鎖
*/
public void method4() {
synchronized (SynMethod.class) {
}
}
wait,notify
private static class MyThread extends Thread {
private synchronized void initString() {
sharedString = "啦啦啦啦";
notifyAll();
}
@Override
public void run() {
super.run();
printString();
}
private synchronized void printString() {
while (sharedString == null) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("String: " + sharedString);
}
}
注意:一定要用while,因爲InterruptedException會打斷,代碼會往下走
join
一個線程插入另一個線程,被插入線程相當於進入wait狀態,在join線程執行完之後會自動調用notify方法
Thread.yield
降低當前線程執行優先級
lock
Lock lock = ...;
lock.lock();
try{
//處理任務
}catch(Exception ex){
}finally{
lock.unlock(); //釋放鎖
}
ReentrantReadWriteLock
ReentrantLock和synchronized基本上都是排它鎖,意味着這些鎖在同一時刻只允許一個線程進行訪問,而讀寫鎖在同一時刻可以允許多個讀線程訪問,在寫線程訪問的時候其他的讀線程和寫線程都會被阻塞。讀寫鎖維護一對鎖(讀鎖和寫鎖),通過鎖的分離,使得併發性提高。