首頁 Java java教程 synchronized鎖住的是程式碼還是對象

synchronized鎖住的是程式碼還是對象

Dec 13, 2016 am 11:10 AM
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方法也相當於全域鎖,相當於鎖住了程式碼段。


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1667
14
CakePHP 教程
1426
52
Laravel 教程
1328
25
PHP教程
1273
29
C# 教程
1255
24
Java中Synchronized的原理與使用場景及Callable介面的使用方法及區別分析 Java中Synchronized的原理與使用場景及Callable介面的使用方法及區別分析 Apr 21, 2023 am 08:04 AM

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

Java關鍵字synchronized原理與鎖定的狀態實例分析 Java關鍵字synchronized原理與鎖定的狀態實例分析 May 11, 2023 pm 03:25 PM

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

Java中如何利用synchronized實作同步機制? Java中如何利用synchronized實作同步機制? Apr 22, 2023 pm 02:46 PM

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

Java中的三種同步方式和它們的使用方法是什麼? Java中的三種同步方式和它們的使用方法是什麼? Apr 27, 2023 am 09:34 AM

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

Java Synchronized鎖定升級原理及流程是什麼 Java Synchronized鎖定升級原理及流程是什麼 Apr 19, 2023 pm 10:22 PM

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

Java中為什麼需要提供Lock,而不只使用synchronized關鍵字? Java中為什麼需要提供Lock,而不只使用synchronized關鍵字? Apr 20, 2023 pm 05:01 PM

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

Java Synchronized是什麼 Java Synchronized是什麼 May 14, 2023 am 08:28 AM

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

Java中Lock和Synchronized的差別是什麼 Java中Lock和Synchronized的差別是什麼 Apr 17, 2023 pm 07:19 PM

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

See all articles