synchronized關鍵字
1 簡單介紹
- synchronized 是java語言關鍵字,當它用來修飾一個方法或者一個代碼塊的時候,能夠保證在同一時刻最多只有一個線程執行該段代碼。
- synchronized 關鍵字,它包括兩種用法:synchronized 方法和 synchronized 塊。
2 可以修飾哪些內容
一、 修飾一個代碼塊,被修飾的代碼塊稱為同步語句塊,其作用的范圍是大括號{}括起來的代碼,作用的對象是調用這個代碼塊的對象;
二、修飾一個方法,被修飾的方法稱為同步方法,其作用的范圍是整個方法,作用的對象是調用這個方法的對象;
三、修飾一個靜態的方法,其作用的范圍是整個靜態方法,作用的對象是這個類的所有對象;
四、修飾一個類,其作用的范圍是synchronized后面括號括起來的部分,作用的對象是這個類的所有對象。
3.synchonized(this)和synchonized(object)區別
其實并沒有很大的區別,synchonized(object)本身就包含synchonized(this)這種情況,使用的場景都是對一個代碼塊進行加鎖,效率比直接在方法名上加synchonized高一些(下面分析),唯一的區別就是對象的不同。
-
對synchronized(this)的一些理解
一、當兩個并發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能有一個線程得到執行。另一個線程必須等待當前線程執行完這個代碼塊以后才能執行該代碼塊。
二、然而,當一個線程訪問object的一個synchronized(this)同步代碼塊時,另一個線程仍然可以訪問該object中的非synchronized(this)同步代碼塊。
三、尤其關鍵的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。
四、當一個線程訪問object的一個synchronized(this)同步代碼塊時,它就獲得了這個object的對象鎖。結果,其它線程對該object對象所有同步代碼部分的訪問都被暫時阻塞。
4.sychonized method 和 synchonized代碼塊的效率問題
- 使用前者的對象會獲取該對象中所有synchonized的鎖,也就是其他線程不能訪問所有加了synchonized前綴的方法(不僅僅只是當前運行的方法),影響了其他線程同步方法的訪問,降低了效率。而后者只對當前代碼塊加鎖,其他的同步方法不受影響。
5.結論
1.synchronized 方法控制對類成員變量的訪問:每個類實例對應一把鎖,每個 synchronized 方法都必須獲得調用該方法的類實例的鎖方能執行,否則所屬線程阻塞,方法一旦執行,就獨占該鎖,直到從該方法返回時才將鎖釋放,此后被阻塞的線程方能獲得該鎖,重新進入可執行狀態。這種機制確保了同一時刻對于每一個類實例,其所有聲明為 synchronized 的成員函數中至多只有一個處于可執行狀態(因為至多只有一個能夠獲得該類實例對應的鎖),從而有效避免了類成員變量的訪問沖突(只要所有可能訪問類成員變量的方法均被聲明為 synchronized)。
2.synchronized 塊是這樣一個代碼塊,其中的代碼必須獲得對象 syncObject (如前所述,可以是類實例或類)的鎖方能執行。由于可以針對任意代碼塊,且可任意指定上鎖的對象,故靈活性較高。
3.在static方法前加synchronized:靜態方法屬于類方法,它屬于這個類,獲取到的鎖,是屬于類的鎖。
4.在普通方法前加synchronized:非static方法獲取到的鎖,是屬于當前對象的鎖。
5.類鎖和對象鎖不同,synchronized修飾不加static的方法,鎖是加在單個對象上,不同的對象沒有競爭關系;修飾加了static的方法,鎖是加載類上,這個類所有的對象競爭一把鎖。