1. 程式人生 > >執行緒高階篇-Synchronized鎖,Lock鎖區別和Condition執行緒並行

執行緒高階篇-Synchronized鎖,Lock鎖區別和Condition執行緒並行

淺談Synchronized:

synchronized是Java的一個關鍵字,也就是Java語言內建的特性,如果一個程式碼塊被synchronized修飾了,當一個執行緒獲取了對應的鎖,執行程式碼塊時,其他執行緒
便只能一直等待,等待獲取鎖的執行緒釋放鎖,而獲取鎖的執行緒釋放鎖會有三種情況:
1).獲取鎖的執行緒執行完該程式碼塊,然後執行緒釋放對鎖的佔有;
2).執行緒執行發生異常,此時JVM會讓執行緒自動釋放鎖;
3).呼叫wait方法,在等待的時候立即釋放鎖,方便其他的執行緒使用鎖.

Lock的特性:

1).Lock不是Java語言內建的;
2).synchronized是在JVM層面上實現的,如果程式碼執行出現異常,JVM會自動釋放鎖,但是Lock不行,要保證鎖一定會被釋放,就必須將unLock放到finally{}中(手動釋放);
3).在資源競爭不是很激烈的情況下,Synchronized的效能要優於ReetarntLock,但是在很激烈的情況下,synchronized的效能會下降幾十倍;
4).ReentrantLock增加了鎖:
a. void lock(); // 無條件的鎖;
b. void lockInterruptibly throws InterruptedException;//可中斷的鎖;
解釋:  使用ReentrantLock如果獲取了鎖立即返回,如果沒有獲取鎖,當前執行緒處於休眠狀態,直到獲得鎖或者當前執行緒可以被別的執行緒中斷去做其他的事情;但是如果是synchronized的話,如果沒有獲取到鎖,則會一直等待下去;
c. boolean tryLock();//如果獲取了鎖立即返回true,如果別的執行緒正持有,立即返回false,不會等待;
d. boolean tryLock(long timeout,TimeUnit unit);//如果獲取了鎖立即返回true,如果別的執行緒正持有鎖,會等待引數給的時間,在等待的過程中,如果獲取鎖,則返回true,如果等待超時,返回false;
5)Lock的ReentrantReadWriteLock讀寫鎖 適用於 讀多寫少的場景 效率較高

Condition的特性:

1.Condition中的await()方法相當於Object的wait()方法,Condition中的signal()方法相當於Object的notify()方法,Condition中的signalAll()相當於Object的notifyAll()方法。不同的是,Object中的這些方法是和同步鎖捆綁使用的;而Condition是需要與互斥鎖/共享鎖捆綁使用的。
2.Condition它更強大的地方在於:能夠更加精細的控制多執行緒的休眠與喚醒。對於同一個鎖,我們可以建立多個Condition,在不同的情況下使用不同的Condition。
    例如,假如多執行緒讀/寫同一個緩衝區:當向緩衝區中寫入資料之後,喚醒”讀執行緒”;當從緩衝區讀出資料之後,喚醒”寫執行緒”;並且當緩衝區滿的時候,”寫執行緒”需要等待;當緩衝區為空時,”讀執行緒”需要等待。
如果採用Object類中的wait(), notify(), notifyAll()實現該緩衝區,當向緩衝區寫入資料之後需要喚醒”讀執行緒”時,不可能通過notify()或notifyAll()明確的指定喚醒”讀執行緒”,而只能通過notifyAll喚醒所有執行緒(但是notifyAll無法區分喚醒的執行緒是讀執行緒,還是寫執行緒)。 但是,通過Condition,就能明確的指定喚醒讀執行緒。

例項

ListAdd.java 使用synchronized

package ThreadCollections;


import java.util.ArrayList;
import java.util.List;

/**
 * Created by 胖大星 on 2017/9/12.
 */
public class ListAdd {
   private volatile static  List list = new ArrayList();

   public void addList(){
       list.add("hello");
   }

   public
int size(){ return list.size(); } public static void main(String[] agrs){ final ListAdd list1 = new ListAdd(); Object lock = new Object(); Thread thread = new Thread(new Runnable(){ @Override public void run() { try { synchronized (lock){ for (int i = 0; i < 10; i++) { list1.addList(); System.out.println("當前執行緒為: "+Thread.currentThread().getName()+" "+i); Thread.sleep(500); if(list.size() == 5){ System.out.println("當前通知已發出!"); lock.notify(); } } } } catch (InterruptedException e){ e.printStackTrace(); } } },"t1"); Thread thread2 = new Thread(new Runnable() { @Override public void run() { synchronized (lock) { if (list1.size() != 5) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("當前執行緒:" + Thread.currentThread().getName()+"已經收到通知"); throw new RuntimeException(); } } },"t2"); thread2.start(); thread.start(); } }

UseReentrantLock.java 使用Lock

package Lock;

import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by 胖大星 on 2017/9/17.
 * Lock 比 synchronized 方法更加便捷,靈活
 */
public class UseReentrantLock {
    //new ReentrantLock(false) 可以帶引數 false 表示非公平鎖(根據cpu分配優先執行) true表示公平鎖(先來先執行)
    private ReentrantLock lock = new ReentrantLock();
    public void method1(){
        try {
            lock.lock();
            System.out.println("當前執行緒:"+Thread.currentThread().getName()+"進入method1...");
            Thread.sleep(1000);
            System.out.println("當前執行緒:"+Thread.currentThread().getName()+"退出method1...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void method2(){
        try {
            lock.lock();
            System.out.println("當前執行緒:"+Thread.currentThread().getName()+"進入method2...");
            Thread.sleep(1000);
            System.out.println("當前執行緒:"+Thread.currentThread().getName()+"退出method2...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        UseReentrantLock useReentrantLock = new UseReentrantLock();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                useReentrantLock.method1();
                useReentrantLock.method2();
            }
        }, "t1");

        t1.start();
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

UseManyCondition.java 使用多個Condition

package Lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * Created by 胖大星 on 2017/9/17.
 *啟動多個 Condition 並行鎖  同時並行多個執行緒
 */
public class UseManyCondition {

    private ReentrantLock lock = new ReentrantLock();
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();

    public void m1(){
        try {
            lock.lock();
            System.out.println("當前執行緒:" +Thread.currentThread().getName() + "進入方法m1等待..");
            c1.await();
            System.out.println("當前執行緒:" +Thread.currentThread().getName() + "方法m1繼續..");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void m2(){
        try {
            lock.lock();
            System.out.println("當前執行緒:" +Thread.currentThread().getName() + "進入方法m2等待..");
            c1.await();
            System.out.println("當前執行緒:" +Thread.currentThread().getName() + "方法m2繼續..");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void m3(){
        try {
            lock.lock();
            System.out.println("當前執行緒:" +Thread.currentThread().getName() + "進入方法m3等待..");
            c2.await();
            System.out.println("當前執行緒:" +Thread.currentThread().getName() + "方法m3繼續..");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void m4(){
        try {
            lock.lock();
            System.out.println("當前執行緒:" +Thread.currentThread().getName() + "喚醒..");
            c1.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void m5(){
        try {
            lock.lock();
            System.out.println("當前執行緒:" +Thread.currentThread().getName() + "喚醒..");
            c2.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {


        final UseManyCondition umc = new UseManyCondition();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                umc.m1();
            }
        },"t1");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                umc.m2();
            }
        },"t2");
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                umc.m3();
            }
        },"t3");
        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                umc.m4();
            }
        },"t4");
        Thread t5 = new Thread(new Runnable() {
            @Override
            public void run() {
                umc.m5();
            }
        },"t5");

        t1.start(); // c1
        t2.start(); // c1
        t3.start(); // c2


        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        t4.start(); // c1
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t5.start(); // c2

    }



}

UseReentrantReadWriteLock.java Lock使用讀寫鎖

package Lock;

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Created by 胖大星 on 2017/9/17.
 * lock的ReentrantReadWriteLock讀寫鎖  適用於 讀多寫少的場景 效率較高
 */
public class UseReentrantReadWriteLock {
    private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    private ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
    private ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();

    public void read(){
        try {
            readLock.lock();
            System.out.println("當前執行緒:"+Thread.currentThread().getName()+"進入....");
            Thread.sleep(3000);
            System.out.println("當前執行緒:"+Thread.currentThread().getName()+"退出....");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            readLock.unlock();
        }
    }

    public void write(){
        try {
            writeLock.lock();
            System.out.println("當前執行緒:"+Thread.currentThread().getName()+"進入....");
            Thread.sleep(3000);
            System.out.println("當前執行緒:"+Thread.currentThread().getName()+"退出....");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            writeLock.unlock();
        }
    }

    public static void main(String[] args) {
        UseReentrantReadWriteLock useReentrantReadWriteLock = new UseReentrantReadWriteLock();
        Thread threadRead1 = new Thread(new Runnable() {
            @Override
            public void run() {
                useReentrantReadWriteLock.read();
            }
        }, "threadRead1");
      Thread threadRead2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    useReentrantReadWriteLock.read();
                }
            }, "threadRead2");

        Thread threadWrite1 = new Thread(new Runnable() {
            @Override
            public void run() {
                useReentrantReadWriteLock.write();
            }
        }, "threafWrite1");

        Thread threadWrite2 = new Thread(new Runnable() {
            @Override
            public void run() {
                useReentrantReadWriteLock.write();
            }
        }, "threafWrite2");

        //兩個讀執行緒同時開始 ,寫執行緒明顯較慢
        threadRead1.start();
       // threadRead2.start();
        threadWrite1.start();
      //  threadWrite2.start();
    }
}

相關推薦

執行高階-SynchronizedLock區別Condition執行並行

淺談Synchronized: synchronized是Java的一個關鍵字,也就是Java語言內建的特性,如果一個程式碼塊被synchronized修飾了,當一個執行緒獲取了對應的鎖,執行程式碼塊時,其他執行緒 便只能一直等待,等待獲取鎖的執行

java第18天----生產者消費者Lock守護執行join()方法

昨天知識總結: 多執行緒 執行緒的兩種建立方式 建立Thread的子類 執行緒與任務分離 執行緒安全----重點 單例中執行緒安全的應用 執行緒的停止 執行緒 執行緒的通訊 執行緒的通訊: 分析: 需要兩個執行緒—輸入執行緒,和輸

C語言高階 - 4.連結串列&狀態機與多執行

1.連結串列的引入 1、從陣列的缺陷說起         (1)陣列有2個缺陷,一個是陣列中所有元素的型別必須一致;第二個是陣列的元素個數必須事先制定並且一旦指定之後不能更改。         (2)如何解決

執行:死樂觀悲觀

死鎖: 兩個或者多個程序競爭統一資源而形成的僵持的局面,若無外力作用,將無法推進。 本質原因: 1)系統資源有限 2)程序推進順序不合理 死鎖的條件: (1)互斥。某個資源在一段時間只能有一個程序佔有,只有當使用該資源的程序釋放後,其他程序才能佔有該資源。 (2

執行與高併發基礎一(超發--悲觀樂觀

關鍵詞: 執行緒,同步,單例,高併發,高訪問,死鎖 一、大規模併發帶來的挑戰 在過去的工作中,我曾經面對過5w每秒的高併發秒殺功能,在這個過程中,整個Web系統遇到了很多的問題和挑戰。如果Web系統不做針對性的優化,會輕而易舉地陷入到異常狀態。我們現在一起來討論下

-1-5 java 多執行緒 概念 程序 執行緒區別聯絡 java建立執行緒方式 執行緒執行緒池概念 執行緒安全 同步 同步程式碼塊 Lock鎖 sleep()wait()方法的區別 為什麼wait(),notify(),notifyAll()等方法都定義在O

 本文關鍵詞: java 多執行緒 概念 程序 執行緒區別聯絡 java建立執行緒方式 執行緒組 執行緒池概念 執行緒安全 同步 同步程式碼塊 Lock鎖  sleep()和wait()方法的區別 為什麼wait(),notify(),notifyAll()等方法都定義在Object類中 多執行緒

Java多執行的死飢餓

死鎖:是指兩個或兩個以上的程序(或執行緒)在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的程序稱為死鎖程序。 死鎖發生在當一些程序請求其他程序佔有的資源而被阻塞時。 死鎖發

執行同步理解(二)——lock方式

  上篇文章,已經提了同步鎖的synchronized的物件鎖和類鎖。這一節我決定研究lock鎖的實現方式。lock鎖可以做到執行緒同步,也就是在多執行緒裡面實現加鎖,同步。    一、同一個物件同步鎖的區域性lock。            為同一個物件呼叫同一個方法的時候

執行同步(執行安全處理Synchronized)與死

一  執行緒同步 java中提供了執行緒同步機制,它能夠解決上述的執行緒安全問題。          執行緒同步的方式有兩種: 方式1:同步程式碼塊   方式2:同步方法 1 同步程式碼塊 同步程式

1執行同步:互斥量

 1執行緒為什麼要同步 A:共享資源,多個執行緒都可對共享資源操作。 B:執行緒操作共享資源的先後順序不確定。 C:處理器對儲存器的操作一般不是原子操作。 2互斥量 mutex操作原語

mysql 開發進階系列 14 問題(避免死查看分析)

mysq cit 優化 業務流程 update span tro isp 問題 一. 概述   通常來說,死鎖都是應用設計問題,通過調整業務流程,數據庫對象設計,事務大小,以及訪問數據庫的sql語句,絕大部分死鎖都可以避免,下面介紹幾種避免死鎖的常用 方法.  1. 在應

執行本地變數的理解將登入資訊存放到執行本地變數中

      在獲取使用者的登入資訊時,我們一般從ThreadLocalMap中獲取,ThreadLocalMap中存放的變數就是執行緒本地的變數,是執行緒隔離的,使用執行緒本地變數而非區域性變數的原因:方便我們對這些變數統一管理,免去頻繁地傳參。 ThreadLocal 原

Java多執行程式設計-(5)-使用Lock物件實現同步以及執行間通訊

前幾篇: 在《Java多執行緒程式設計-(4)-執行緒間通訊機制的介紹與使用》已經學習了,可以使用方法wait/notify 結合同步關鍵字syn

Python實戰之processing程序(多程序程序池lock程序間的通訊)

首先須知 什麼是IO? 從硬碟讀塊資料,從網路讀塊資料屬於IO操作(IO操作不佔用cpu) 計算佔用cpu,如:1+1 Python多執行緒其實就是一個執行緒,由於利用CUP的上下文切換看起來就像是併發..上下文切換消耗資源 Python多執行緒 不適合CPU密集操作型的任務,適

執行:synchronize、volatile、Lock區別與用法

Java多執行緒之記憶體可見性和原子性:Synchronized和Volatile的比較       在說明Java多執行緒記憶體可見性之前,先來簡單瞭解一下Java記憶體模型。     

程序執行程式的區別聯絡

程序和程式區別和聯絡表現在以下方面: 1)程式只是一組指令的有序集合,它本身沒有任何執行的含義,它只是 一個靜態的實體。而程序則不同,它是程式在某個資料集上的執行。 程序是一個動態的實體,它有自己的生命週期。它因建立而產生,因 排程而執行,因等待資源或事件而被處於等待

Spark修煉之道(高階)——Spark原始碼閱讀:第八節 Task執行

Task執行 在上一節中,我們提到在Driver端CoarseGrainedSchedulerBackend中的launchTasks方法向Worker節點中的Executor傳送啟動任務命令,該命令的接收者是CoarseGrainedExecutorBack

synchronized實現原理及其優化-(自旋偏向輕量重量

1.synchronized概述:   synchronized修飾的方法或程式碼塊相當於併發中的臨界區,即在同一時刻jvm只允許一個執行緒進入執行。synchronized是通過鎖機制實現同一時刻只允許一個執行緒來訪問共享資源的。另外synchronized鎖機制還可以保證執行緒併發執行的原子性,有序性,可

C# lock 語法糖實現原理--《.NET Core 底層入門》之自旋互斥混合讀寫

在多執行緒環境中,多個執行緒可能會同時訪問同一個資源,為了避免訪問發生衝突,可以根據訪問的複雜程度採取不同的措施 原子操作適用於簡單的單個操作,無鎖演算法適用於相對簡單的一連串操作,而執行緒鎖適用於複雜的一連串操作 ### 原子操作 修改狀態要麼成功且狀態改變,要麼失敗且狀態不變,並且外部只能觀察到修改

<Linux> 文件夾右下角有

text https href user targe vps amp 路徑 pyw sudo chown -R $USER 文件夾路徑 例如:sudo chown -R $USER ~/scala<Linux> 文件夾右下角有鎖,解鎖