synchronized鎖住的是程式碼還是對象
在Java中,synchronized關鍵字是用來控制執行緒同步的,就是在多執行緒的環境下,控制synchronized程式碼段不被多個執行緒同時執行。 synchronized既可以加在一段程式碼上,也可以加在方法上。
關鍵是,不要認為給方法或程式碼段加上synchronized就萬事大吉,看下面一段程式碼:
public synchronized void test() { System.out.println("test开始.."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("test结束.."); } } class MyThread extends Thread { public void run() { Sync sync = new Sync(); sync.test(); } } public class Main { public static void main(String[] args) { for (int i = 0; i < 3; i++) { Thread thread = new MyThread(); thread.start(); } } }
運行結果: test開始.. test開始.. test開始.. test結束.. test結束.. test結束..
可以看出來,上面的程式起了三個線程,同時運行Sync類中的test()方法,雖然test()方法加上了synchronized,但是還是同時運行起來,貌似synchronized沒起作用。
將test()方法上的synchronized去掉,在方法內部加上synchronized(this):
public void test() { synchronized(this){ System.out.println("test开始.."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("test结束.."); } }
運行結果: test開始.. test開始.. test開始.. test結束.. test結束.. test結束..
一切還是這麼平靜,沒有看到synchronized起到作用。
實際上,synchronized(this)以及非static的synchronized方法(至於static synchronized方法請往下看),只能防止多個執行緒同時執行同一個物件的同步程式碼段。
回到本文的題目上:synchronized鎖住的是程式碼還是物件。答案是:synchronized鎖住的是括號裡的對象,而不是程式碼。對於非static的synchronized方法,鎖定的就是物件本身也就是this。
當synchronized鎖住一個物件後,別的執行緒如果也想拿到這個物件的鎖,就必須等待這個執行緒執行完成釋放鎖,才能再次給物件加鎖,這樣才達到執行緒同步的目的。即使兩個不同的程式碼段,都要鎖同一個對象,那麼這兩個程式碼段也不能在多執行緒環境下同時運作。
所以我們在用synchronized關鍵字的時候,能縮小程式碼段的範圍就盡量縮小,能在程式碼段上加同步就不要再整個方法上加同步。這叫做減小鎖的粒度,使程式碼更大程度的並發。原因是基於以上的思想,鎖的程式碼片段太長了,別的線是不是要等很久,等的花兒都謝了。當然這段是題外話,與本文核心思想並無太大關聯。
再看上面的程式碼,每個執行緒中都new了一個Sync類別的對象,也就是產生了三個Sync對象,由於不是同一個對象,所以可以多執行緒同時執行synchronized方法或程式碼片段。
為了驗證上述的觀點,修改一下程式碼,讓三個執行緒使用同一個Sync的物件。
class MyThread extends Thread { private Sync sync; public MyThread(Sync sync) { this.sync = sync; } public void run() { sync.test(); } } public class Main { public static void main(String[] args) { Sync sync = new Sync(); for (int i = 0; i < 3; i++) { Thread thread = new MyThread(sync); thread.start(); } } }
運行結果: test開始.. test結束.. test開始.. test結束.. test開始.. test結束..
可以看到,此時的synchronized就起了作用。
那麼,如果真的想鎖住這段程式碼,要怎麼做?也就是,如果還是最開始的那段程式碼,每個執行緒new一個Sync對象,怎麼才能讓test方法不會被多執行緒執行。
解決也很簡單,只要鎖住同一個物件不就行了。例如,synchronized後的括號中鎖同一個固定對象,這樣就行了。這樣是沒問題,但是,比較多的做法是讓synchronized鎖這個類別對應的Class物件。
class Sync { public void test() { synchronized (Sync.class) { System.out.println("test开始.."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("test结束.."); } } } class MyThread extends Thread { public void run() { Sync sync = new Sync(); sync.test(); } } public class Main { public static void main(String[] args) { for (int i = 0; i < 3; i++) { Thread thread = new MyThread(); thread.start(); } } }
運行結果: test開始.. test結束.. test開始.. test結束.. test開始.. test結束..
上面程式碼用synchronized(Sync.class)實現了全域鎖定的效果。
static synchronized方法,static方法可以直接類別名稱加方法名稱調用,方法中無法使用this,所以它鎖的不是this,而是類別的Class對象,所以,static synchronized方法也相當於全域鎖,相當於鎖住了程式碼段。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

一、基本特性1.一開始是樂觀鎖,如果鎖衝突頻繁,就轉換為悲觀鎖.2.開始是輕量級鎖實現,如果鎖被持有的時間較長,就轉換成重量級鎖. 3.實現輕量級鎖的時候大概率用到的自旋鎖策略4.是一種不公平鎖5.是一種可重入鎖6.不是讀寫鎖二、加鎖工作過程JVM將synchronized鎖分為無鎖、偏向鎖、輕量級鎖、重量級鎖狀態。會根據情況,進行依序升級。偏向鎖假設男主角是一個鎖,女主角是一個線程.如果只有這一個線程來使用這個鎖,那麼男主女主即使不領證結婚(避免了高成本操作),也可以一直幸福的生活下去.但是女配出現

一、Java中鎖的概念自旋鎖:是指當一個線程獲取鎖的時候,如果鎖已經被其它線程獲取,那麼該線程將循環等待,然後不斷的判斷鎖是否能被成功獲取,直到獲取到鎖才會退出循環。樂觀鎖:假定沒有衝突,在修改數據時如果發現數據和先前取得的不一致,則讀最新數據,重試修改。悲觀鎖:假定會發生並發衝突,同步所有對資料的相關操作,從讀取資料就開始上鎖。獨享鎖(寫):給資源加上寫鎖,執行緒可以修改資源,其它執行緒不能再加鎖(單一寫)。共享鎖(讀):給資源加上讀鎖後只能讀不能修改,其它執行緒也只能加讀鎖,不能加寫鎖(多度)。看成S

Java的synchronized使用方法總結1.把synchronized當作函數修飾符時,範例程式碼如下:Publicsynchronizedvoidmethod(){//….}這也就是同步方法,那這時synchronized鎖定的是哪個物件呢?他鎖定的是呼叫這個同步方法物件。也就是說,當一個物件P1在不同的執行緒中執行這個同步方法時,他們之間會形成互斥,達到同步的效果。但是這個物件所屬的Class所產生的另一物件P2卻能夠任意呼叫這個被加了synchronized關鍵字的方法。上邊的範例程式碼等

1.說明synchronized算是我們最常用的同步方式,主要有三種使用方式。 2.實例//普通類別方法同步synchronizedpublidvoidinvoke(){}//類別靜態方法同步synchronizedpublicstaticvoidinvoke(){}//程式碼區塊同步synchronized(object){}這三種方式的不同之處在於同步的物件不同,普通類別synchronized同步的是物件本身,靜態方法同步的是類別Class本身,程式碼區塊同步的是我們在括號內部填入的物件。 Java有哪些集合

工具準備在正式談synchronized的原理之前我們先談一下自旋鎖,因為在synchronized的優化當中自旋鎖發揮了很大的作用。而需要了解自旋鎖,我們首先要了解什麼是原子性。所謂原子性簡單說來就是一個一個操作要么不做要么全做,全做的意思就是在操作的過程當中不能夠被中斷,比如說對變量data進行加一操作,有以下三個步驟:將data從記憶體載入到暫存器。將data這個值加一。將得到的結果寫回記憶體。原子性就表示一個執行緒在進行加一操作的時候,不能夠被其他執行緒中斷,只有這個執行緒執行完這三個過程的時候

摘要:在Java中提供了synchronized關鍵字來保證只有一個執行緒能夠存取同步程式碼區塊。既然已經提供了synchronized關鍵字,為何在Java的SDK包中,還會提供Lock介面呢?這是不是重複造輪子,多此一舉呢?今天,我們就一起來探討下這個問題。在Java中提供了synchronized關鍵字來保證只有一個執行緒能夠存取同步程式碼區塊。既然已經提供了synchronized關鍵字,為何在Java的SDK包中,還會提供Lock介面呢?這是不是重複造輪子,多此一舉呢?今天,我們就一起來探討下

Synchronized是什麼各位Java讀者,對於synchronized關鍵字並不陌生,在各種中間件源碼或JDK源碼中都能看到,對於不熟悉synchronized的讀者只知道在多線程中需要使用到synchronized關鍵字,知道synchronized能夠保證線程安全。稱之為:互斥鎖(同時只能一個執行緒執行,其他的執行緒將會等待)又稱之為:悲觀鎖(同時只能一個執行緒執行,其他的執行緒將會等待)JVM虛擬機幫你實現,開發者只需要使用synchronized關鍵字即可。使用時需要用一個物件當鎖的互斥

1.從功能角度來看Lock和Synchronized都是java中去用來解決線程安全問題的一個工具2.從特性來看Synchronized是java中的同步關鍵字,Lock是J.U.C包中提供的接口,而這個介面有很多的實現類,包括ReentrantLock這樣重入鎖的實現,Synchronized可以透過兩種方式去控制鎖的力度一種把synchronized關鍵字修飾在方法層面,另一種是修飾在程式碼區塊上,可以透過synchronized加鎖物件的生命週期,來控制鎖的作用範圍,鎖定物件是靜態物件或類別對
