1. 程式人生 > >Java併發之synchronized關鍵字和Lock介面

Java併發之synchronized關鍵字和Lock介面

歡迎點贊閱讀,一同學習交流,有疑問請留言 。
GitHub上也有開源 JavaHouse,歡迎star

引用

當開發過程中,我們遇到併發問題。怎麼解決?

一種解決方式,簡單粗暴:上鎖。將千軍萬馬都給攔下來,只允許一個人過獨木橋。書面意思就是將並行的程式變成序列的程式。現實的鎖有門鎖、掛鎖和抽屜鎖等等。在Java中,我們的鎖就是synchronized關鍵字和Lock介面。

synchronized關鍵字

synchronized也叫同步鎖,是Java裡面的關鍵字。我們可以猜測到synchronized原理也JVM虛擬機器有關聯。

synchronized鎖的是物件。物件裡面有一個叫做監視鎖(monitor)的東西,監視鎖依賴作業系統的互斥鎖(Mutex Lock)。作業系統切換執行緒其實就是從使用者態程式設計核心態(cpu的兩種狀態)。這個代價有點高,所以synchronized這個重量級鎖後面也引進了偏向鎖和輕量級鎖。

加鎖(監視鎖monitor)過程分析():

  1. 當monitor的進入數為0,執行緒A進入
  2. monitor的進入數為1
  3. 執行緒B想進入該monitor就會被阻塞。

執行緒A可以重複進入該monitor,所以synchronized是可重入鎖,和Lock實現的鎖一樣。

  • 程式驗證
public class SynchronizedTest {
    private static  int i = 0;
    public static void main(String[] args) {
        test();
    }

    public static void test(){
        synchronized (SynchronizedTest.class){
            synchronized (SynchronizedTest.class){
                i++;
            }
        }
    }
}
  • 執行結果
    程式正常執行,沒有報錯

synchronized可以修飾方法以及程式碼塊,程式碼塊就是上面重入鎖的例子。

  • 修飾方法
public class SynchronizedTest {
    static int n = 100;
    final static CountDownLatch start = new CountDownLatch(n);
    private static  int i = 0;
    public static void main(String[] args) throws InterruptedException {
        for (int j = 0; j < n; j++) {
            Thread thread = new Thread(new addNoSynchronized());
            thread.start();
        }
        start.await();
        System.out.println(i);
    }

    public static class addSynchronized implements Runnable{
        @Override
        public void run() {
            addSynchronized();
        }
        public static synchronized void addSynchronized(){
            for (int j = 0; j < 1000; j++) {
                i++;
            }
            start.countDown();
        }
    }
}
  • 執行結果
100000

如果去掉 synchronized 關鍵字的話,執行結果大概率不是 100000,因為執行緒不安全問題。

Lock介面

一般我們使用 ReentrantLock 類作為重入鎖,實現Lock介面。

  • 使用方法
public class ReentranLockTest {
    private static int j;
    private static int n = 100;
    private static CountDownLatch latch = new CountDownLatch(n);
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < n; i++) {
            new Thread(new LockTest()).start();
        }
        latch.await();
        System.out.println("結果為:"+j);
    }

    public static class LockTest implements Runnable{
        static Lock lock = new ReentrantLock();
        @Override
        public void run() {
            lockTest();
            latch.countDown();
        }
        private void lockTest() {
            lock.lock();
            try {
                for (int i = 0; i < 1000; i++) {
                        j++;
                }
            }finally {
                lock.unlock();
            }
        }
    }
}
  • 執行結果
結果為:100000

這裡我們鎖住的 j++ 這塊資源區(公共資源),lock 是 static 關鍵字修飾的,是類物件,思考一下如果不是類物件會怎麼樣?那就是連環鎖了(看圖)。

每一個執行緒都對可以用鑰匙解開這把鎖,對於程式而言,加鎖操作就沒有意義了。因為我們需要的是一個鎖。

歡迎關注我的微信公眾號

相關推薦

Java併發synchronized關鍵字Lock介面

歡迎點贊閱讀,一同學習交流,有疑問請留言 。 GitHub上也有開源 JavaHouse,歡迎star 引用 當開發過程中,我們遇到併發問題。怎麼解決? 一種解決方式,簡單粗暴:上鎖。將千軍萬馬都給攔下來,只允許一個人過獨木橋。書面意思就是將並行的程式變成序列的程式。現實的鎖有門鎖、掛鎖和抽屜鎖等等。

Java併發synchronized關鍵字深度解析(一)

前言         近期研讀路神之絕世武學,徜徉於浩瀚無垠知識之海洋,偶有攫取吉光片羽,惶恐未領略其精髓即隱入歲月深處,遂急忙記錄一二,順備來日吹cow之談資。本小系列為併發之親兒子-獨臂狂俠synchronized專場。 一、使用場景     &

Java多線程:synchronized關鍵字Lock

final sleep java多線 大型 pre 有一個 但是 logs 讀寫文件 一、synchronized   synchronized關鍵字可以用於聲明方法,也可以用來聲明代碼塊,下面分別看一下具體的場景(摘抄自《大型網站系統與Java中間件實踐》) 案例一:

Java多執行緒-併發synchronized 關鍵字

synchronized 關鍵字 答: 底層實現: 進入時,執行 monitorenter,將計數器 +1,釋放鎖 monitorexit 時,計數器 -1 當一個執行緒判斷到計數器為 0 時,則當前鎖空閒,可以佔用;反之,當前執行緒進入等待狀態 含義

java併發----volatile關鍵字

一、volatile 在java中,volatile關鍵字解決的是變數在多個執行緒之間的可見性,一旦一個共享變數(類的成員變數、類的靜態成員變數)被volatile修飾之後,那麼就具備了兩層語義: (1)保證了不同執行緒對這個變數進行操作時的可見性,即一個執行緒修改了某個變數的值,這

Java併發程式設計(六)Lock介面

一、Lock介面的引入 由於synchronized關鍵字有些缺陷,如無法響應中斷等,出現了Lock介面。相對於synchronized,Lock有如下補充: Lock可以響應中斷; Lock可以得知執行緒是否已經獲得鎖; Lock可以提供更為複雜的讀寫鎖,以應對讀寫同時存

Java中的transient關鍵字Externalizable介面

一、transient transient 關鍵字可以應用於類的成員變數,以便指出該成員變數不應在包含它的類例項已序列化時被序列化。 若一個類中,有些屬性需要序列化,其他屬性不需要序列化,只要實現Serializable介面,將不需要序列化的屬性前新增關鍵字transien

java併發----synchronized與ReenTrantLock

Java 提供了兩種鎖機制來控制多個執行緒對共享資源的互斥訪問,第一個是 JVM 實現的 synchronized,而另一個是 JDK 實現的 ReentrantLock。 synchronized synchronized關鍵字最主要幾種使用方式: (1)同步一個程式碼塊: 只作用

深入理解Java併發synchronized實現原理

關聯文章: 本篇主要是對Java併發中synchronized關鍵字進行較為深入的探索,這些知識點結合博主對synchronized的個人理解以及相關的書籍的講解(在結尾參考資料),如有誤處,歡迎留言。 執行緒安全是併發程式

java併發程式設計---synchronized關鍵字

 在併發程式設計中,多執行緒同時併發訪問的資源叫做臨界資源,當多個執行緒同時訪問物件並要求操作相同資源時,分割了原子操作就有可能出現數據的不一致或資料不完整的情況,為避免這種情況的發生,我們會採取同步機制,以確保在某一時刻,方法內只允許有一個執行緒。       採用syn

Java併發AQS用法原始碼分析

概念 AQS:佇列同步器AbstractQueuedSynchronizer(以下簡稱同步器),是用來構建鎖或者其他同步元件的基礎框架,許多同步器可以通過AQS很容易的並且高效的構建出來。不僅RenntrantLock和Semaphore是基於AQS構建的,還包括CountDownLat

原始碼閱讀:Java併發synchronized實現原理

執行緒安全是併發程式設計中的重要關注點,應該注意到的是,造成執行緒安全問題的主要誘因有兩點,一是存在共享資料(也稱臨界資源),二是存在多條執行緒共同操作共享資料。因此為了解決這個問題,我們可能需要這樣一個方案,當存在多個執行緒操作共享資料時,需要保證同一時刻有且

深入理解 Java 併發 synchronized 實現原理

關聯文章深入理解Java型別資訊(Class物件)與反射機制深入理解Java列舉型別(enum)深入理解Java註解型別(@Annotation)深入理解Java併發之synchronized實現原理本篇主要是對Java併發中synchronized關鍵字進行較為深入的探索,這些知識點結合博主對synchro

java 併發 synchronized 實現原理

在 java 開發中 synchronized 是使用的最多的工具。 表現形式 在 java 中每個物件都可以作為鎖: 對於普通同步方法,鎖是當前例項物件; 對於靜態同步方法,鎖是當前類的 Class 物件; 對於同步方法快,鎖是 Synchronized 括

java基礎Synchronized關鍵字

Java中Synchronized的用法 總結: A. 無論synchronized關鍵字加在方法上還是物件上,如果它作用的物件是非靜態的,則它取得的鎖是物件;如果synchronized作用的物件是一個靜態方法或一個類,則它取得的鎖是對類,該類所有的物件同一把鎖

Java併發volatile關鍵字

引言 說到多執行緒,我覺得我們最重要的是要理解一個臨界區概念。 舉個例子,一個班上1個女孩子(臨界區),49個男孩子(執行緒),男孩子的目標就是這一個女孩子,就是會有競爭關係(執行緒安全問題)。推廣到實際場景,例如對一個數相加或者相減等等情形,因為操作物件就只有一個,在多執行緒環境下,就會產生執行緒安全問

《提升能力,漲薪可待》—Java併發Synchronized

Synchronized簡介 執行緒安全是併發程式設計中的至關重要的,造成執行緒安全問題的主要原因: 臨界資源, 存在共享資料 多執行緒共同操作共享資料 而Java關鍵字synchronized,為多執行緒場景下防止臨界資源訪問衝突提供支援, 可以保證在同一時刻,只有一個執行緒可以執行某個方

java併發synchronized

Java為我們提供了隱式(synchronized宣告方式)和顯式(java.util.concurrentAPI程式設計方式)兩種工具來避免執行緒爭用。 本章節探索Java關鍵字synchronized。主要包含以下幾個內容。 - synchronized關鍵字的使用; - synchronized背後

Java併發程式設計synchronized關鍵字(二)

上一篇文章講了synchronized的部分關鍵要點,詳見:Java高併發程式設計之synchronized關鍵字(一) 本篇文章接著講synchronized的其他關鍵點。 在使用synchronized關鍵字的時候,不要以字串常量作為鎖定物件。看下面的例子: public class

Java併發程式設計synchronized關鍵字(一)

首先看一段簡單的程式碼: public class T001 { private int count = 0; private Object o = new Object(); public void m() { //任何執行緒要執行下面這段程式碼