线程:synchronized
?對象鎖?
? 關鍵字synchronized取得的鎖都是對象鎖,而不是把一段代碼或方法(函數)當做鎖。
?
? 鎖重入
? synchronized擁有鎖重入功能,也就是在使用synchronized時, 當一個線程得到一個對象鎖后,再次請求此對象鎖時是可以再次得到該對象的鎖的。
? 可重入鎖: 自己可以再次獲取自己的內部鎖。
?
public class Service {synchronized public void service1(){System.out.println("service1...");service2();}synchronized public void service2(){System.out.println("service2...");service3();}synchronized public void service3(){System.out.println("service3...");} }?
當存在父子類繼承關系時,子類是完全可以通過"可重入鎖"調用父類的同步方法的。
public class Main {public int i = 10;synchronized public void operateMainMethod(){try{i--;System.out.println("main print i="+i);Thread.sleep(1000);}catch(InterruptedException e){e.printStackTrace();}} }public class Sub extends Main {synchronized public void operateISubMethod(){try{while(i>0){i--;System.out.println("sub print i="+i);Thread.sleep(100);this.operateMainMethod();}}catch(InterruptedException e){e.printStackTrace();}} }出現異常,鎖自動釋放
? 當一個線程執行的代碼出現異常時,其所持有的鎖會自動釋放。
?
同步不具有繼承性
? 同步是無法繼承的
public class Main {synchronized public void serviceMethod(){try{System.out.println("int main 下一步 sleep begin threadName="+Thread.currentThread().getName() +" time="+System.currentTimeMillis());Thread.sleep(5000);System.out.println("int main 下一步 sleep end threadName="+Thread.currentThread().getName() +" time="+System.currentTimeMillis());}catch(InterruptedException e){e.printStackTrace();}} }public class Sub extends Main{@Overridepublic void serviceMethod(){try{System.out.println("int sub 下一步 sleep begin threadName="+Thread.currentThread().getName() +" time="+System.currentTimeMillis());Thread.sleep(5000);System.out.println("int sub 下一步 sleep end threadName="+Thread.currentThread().getName() +" time="+System.currentTimeMillis());}catch(InterruptedException e){e.printStackTrace();}} }synchronized同步語句塊
? ?1. synchronized方法是對當前對象進行加鎖, 而synchronized代碼塊是對某一個對象進行加鎖。
? ?2. synchronized代碼塊間也具有同步性, 當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對同一個object中所有其他synchronized(this)同步代碼塊的訪問將被阻塞,這說明synchronized使用的"對象監視器"是一個。
? ?3. synchronized(this)代碼塊是鎖定當前對象的。
? ?4. 多對象時候,鎖住代碼
? ? ? ? 只要鎖住同一個對象就行了。例如:synchronized后的括號中鎖同一個固定對象,這樣就行了。?這樣是沒問題,但是,比較多的做法是讓synchronized鎖這個類對應的Class對象。
public class Sync2 {public void test() {synchronized (Sync2.class) {System.out.println("test start");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("test end");}} }public class MyThread3 extends Thread{public void run() {Sync2 sync = new Sync2();sync.test();}public static void main(String[] args) {for (int i = 0; i < 3; ++i) {Thread thread = new MyThread3();thread.start();}} }?執行結果:
test start
test end
test start
test end
test start
test end
?
靜態同步synchronized方法與synchronized(class)代碼塊
? 關鍵字synchronized還可以應用在static靜態方法上,這是對當前的*.java文件對應的Class類進行持鎖。
??synchronized加到static靜態方法上是給Class類上鎖, 而synchronized關鍵字加到非static靜態方法上是給對象上鎖。
? Class鎖可以對類的所有對象實例起作用。
?
數據類型String的常量池特性
? jvm中具有String常量池緩存的功能,因此大多數情況下,同步synchronized代碼塊都不使用String作為鎖對象,而改用其他。
?
方法幀: 第一塊:局部變量表? ?第二塊:操作數棧? 第三塊:指向常量池的指針。
?
?
總結
以上是生活随笔為你收集整理的线程:synchronized的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构:堆排序一(heap sort)
- 下一篇: 线程:volatile关键字