天天看點

JAVA并發程式設計之基本概念

1、鎖是對對象通路的時候,通過對對象加鎖,防止并行通路的控制手段;對對象加鎖成功,代表我持有這個對象的螢幕,解鎖,代表釋放了這個對象的螢幕。

拿到對象的螢幕,肯定是對對象加鎖成功的;對對象加鎖成功 ,程式可以主動Watiing或者Time_waiting在對象螢幕上。

2、鎖與螢幕差別

參見以下文章 Java鎖和螢幕  java-jvm-jstack-(螢幕和鎖的概念) Synchronized的内部實作原理

3、同步隊列與等待隊列

簡單的了解是同步隊列存放着競争同步資源的線程的引用(不是存放線程),而等待隊列存放着待喚醒的線程的引用。

在Object的螢幕模型中,一個對象擁有一個同步隊列和一個等待隊列,而并發包中的Lock(更确切的說是同步器AQS)擁有一個同步隊列和多個等待隊列。

JAVA并發程式設計之基本概念

4、非公平鎖和公平鎖

公平鎖模式,是根據FIFO規則,在同步隊列中,依據線程等待鎖的時間長短,也就是頭結點的下一個節點擷取到鎖。

非公平鎖模式,一個線程在釋放鎖之後,ReentrantLock類從同步隊列中怎麼決定哪個線程可以擷取到鎖的?非公平鎖的非公平體性展現在一個線程會首先嘗試擷取同步狀态,不管同步隊列是否有線程在排隊,這就有可能在其他線程釋放鎖後,目前線程比同步隊列中的線程先擷取到鎖。

以Semaphore類說明:
1、//非公平鎖,在擷取同步狀态時,直接嘗試擷取同步狀态,如果擷取同步狀态成功,則擷取到鎖。注意,非公平鎖的線程并沒有判斷目前同步隊列是否有節點。
final int nonfairTryAcquireShared(int acquires) {
            for (;;) {
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }
2、//公平鎖,在擷取同步狀态時,先判斷目前同步隊列是否有節點,如果有存在等待的節點,則傳回-1,表示擷取鎖失敗
protected int tryAcquireShared(int acquires) {
            for (;;) {
                if (hasQueuedPredecessors())//查詢是否有線程正在等待擷取鎖。
                    return -1;
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }
           

5、自旋鎖

自旋鎖:線程擷取鎖的時候,如果鎖被其他線程持有,則目前線程将循環等待,直到擷取到鎖。

6、happen-before規則

  • 程式次序規則:一個線程内,按照代碼順序,書寫在前面的操作先行發生于書寫在後面的操作;參考這裡:java 8大happen-before原則超全面詳解
  • 鎖定規則:一個unLock操作先行發生于後面對同一個鎖的lock操作;
  • volatile變量規則:對一個變量的寫操作先行發生于後面對這個變量的讀操作; 對一個 volatile 變量的讀,總是能看到(任意線程)對這個 volatile 變量最後的寫入。關于volatile變量的,很重要,看這裡: volatile變量規則:對一個變量的寫操作先行發生于後面對這個變量的讀操作
  • 傳遞規則:如果操作A先行發生于操作B,而操作B又先行發生于操作C,則可以得出操作A先行發生于操作C;
  • 線程啟動規則:Thread對象的start()方法先行發生于此線程的每個一個動作;
  • 線程中斷規則:對線程interrupt()方法的調用先行發生于被中斷線程的代碼檢測到中斷事件的發生;
  • 線程終結規則:線程中所有的操作都先行發生于線程的終止檢測,我們可以通過Thread.join()方法結束、Thread.isAlive()的傳回值手段檢測到線程已經終止執行;

7、偏向鎖,輕量級鎖,重量級鎖

     偏向鎖:偏向鎖是一種針對加鎖操作的優化手段。它的核心思想是:如果一個線程獲得了鎖,那麼鎖就進入偏向模式。當這個線程再次請求鎖時,無須再做任何同步操作。  

     輕量級鎖:輕量級鎖是相對于重量級鎖而言的,而重量級鎖就是傳統的鎖。輕量級鎖是一種樂觀鎖,它認為鎖存在競争的機率比較小,是以它不使用互斥同步,而是使用CAS操作來獲得鎖,這樣能減少互斥同步所使用的互斥量帶來的性能開銷。

    重量級鎖: 重量級鎖是一種悲觀鎖,它認為總是有多條線程要競争鎖,是以它每次處理共享資料時,不管目前系統中是否真的有線程在競争鎖,它都會使用互斥同步來保證線程的安全。    

    鎖更新:參考這個文章,寫的不錯。Java并發——Synchronized關鍵字和鎖更新,詳細分析偏向鎖和輕量級鎖的更新

繼續閱讀