1. 程式人生 > >Java併發程式設計與技術內幕:聊聊鎖的技術內幕(中)

Java併發程式設計與技術內幕:聊聊鎖的技術內幕(中)

      摘要:本文主要講了讀寫鎖。

一、讀寫鎖ReadWriteLock

       在上文中回顧了併發包中的可重入鎖ReentrantLock,並且也分析了它的原始碼。從中我們知道它是一個單一鎖(筆者自創概念),意思是在多人讀、多人寫、或同時有人讀和寫時。只能有一個人能拿到鎖,執行程式碼。但是在很多場景。我們想控制它能多人同時讀,但是又不讓它多人寫或同時讀和寫時。(想想這是不是和資料庫的可重複讀有點型別?),這時就可以使用讀寫鎖:ReadWriteLock。

下面來看一個應用

  1. package com.lin;  
  2. import java.util.concurrent.ExecutorService;  
  3. import java.util.concurrent.Executors;  
  4. import java.util.concurrent.locks.ReadWriteLock;  
  5. import java.util.concurrent.locks.ReentrantReadWriteLock;  
  6. publicclass ReadWriteLockTest {  
  7.    publicstaticvoid main(String[] args) {  
  8.        //建立一個鎖物件 ,非公平鎖
  9.        ReadWriteLock lock = new ReentrantReadWriteLock(
    false);    
  10.        //建立一個執行緒池  
  11.        ExecutorService pool = Executors.newCachedThreadPool();   
  12.        //設定一個賬號,設定初始金額為10000
  13.        Account account = new Account(lock,"123456",10000);  
  14.        //賬號取錢10次,存錢10次,查詢20次
  15.        for(int i=1;i<=10;i++) {  
  16.            Operation operation1 = new Operation(account,"take"
    );  
  17.            Operation operation2 = new Operation(account,"query");  
  18.            Operation operation3 = new Operation(account,"save");  
  19.            Operation operation4 = new Operation(account,"query");  
  20.            pool.execute(operation1);  
  21.            pool.execute(operation2);  
  22.            pool.execute(operation3);  
  23.            pool.execute(operation4);  
  24.        }  
  25.        pool.shutdown();  
  26.        while(!pool.isTerminated()){    
  27.            //wait for all tasks to finish  
  28.        }    
  29.        System.out.println("賬號"+ account.getAccoutNo() +",最後金額為:"+account.getMoney());    
  30.    }  
  31. }  
  32. class Operation implements Runnable{  
  33.     private Account account;//賬號
  34.     private String type;  
  35.     Operation(Account account,String type){  
  36.         this.account = account;  
  37.         this.type = type;  
  38.     }  
  39.     publicvoid run() {  
  40.         if ("take".equals(type)) { //每次取100元
  41.              //獲取寫鎖  
  42.             account.getLock().writeLock().lock();  
  43.             account.setMoney(account.getMoney() -100);  
  44.             System.out.println( "取走100元,賬號"+ account.getAccoutNo()+" 還有"+account.getMoney()+"元");  
  45.             account.getLock().writeLock().unlock();  
  46.         }  
  47.         elseif ("query".equals(type)) {  
  48.              //獲取寫鎖  
  49.             account.getLock().readLock().lock();  
  50.             System.out.println( "查詢賬號"+ account.getAccoutNo()+" 還有"+account.getMoney()+"元");  
  51.             account.getLock().readLock().unlock();  
  52.         }  
  53.         elseif ("save".equals(type)) {  
  54.              //獲取寫鎖  
  55.             account.getLock().writeLock().lock();  
  56.             account.setMoney(account.getMoney() + 100);  
  57.             System.out.println( "存入100元,賬號"+ account.getAccoutNo()+" 還有"+account.getMoney()+"元");  
  58.             account.getLock().writeLock().unlock();  
  59.         }  
  60.     }  
  61. }  
  62. class Account  {  
  63.     privateint money;//賬號上的錢
  64.     private ReadWriteLock lock;//讀寫寫
  65.     private String accoutNo;//賬號
  66.     Account(ReadWriteLock lock,String accoutNo,int money) {  
  67.         this.lock = lock;  
  68.         this.accoutNo = accoutNo;  
  69.         this.money = money;  
  70.     }  
  71.     publicint getMoney() {  
  72.         return money;  
  73.     }  
  74.     publicvoid setMoney(int money) {  
  75.         this.money = money;  
  76.     }  
  77.     public ReadWriteLock getLock() {  
  78.         return lock;  
  79.     }  
  80.     publicvoid setLock(ReadWriteLock lock) {  
  81.         this.lock = lock;  
  82.     }  
  83.     public String getAccoutNo() {  
  84.         return accoutNo;  
  85.     }  
  86.     publicvoid setAccoutNo(String accoutNo) {  
  87.         this.accoutNo = accoutNo;  
  88.     }     
  89. }  
輸出結果:


在上面的例子中,設定了一個賬號。金額為10000,然後開了10條執行緒每次取100,10條執行緒每次存100,20條執行緒一直查。從結果中我們可以看到是正確的。 二、原始碼分析  1、ReadWriteLock
  1. publicinterface ReadWriteLock {  
  2.     Lock readLock();//返回讀鎖
  3.     Lock writeLock();//返回寫鎖
  4. }  

ReadWriteLock就只是一個介面類,真正實現 類在ReentrantReadWriteLock
2、ReentrantReadWriteLock (1)包含變數
  1. publicclass ReentrantReadWriteLock  
  2.         implements ReadWriteLock, java.io.Serializable {  
  3.     privatestaticfinallong serialVersionUID = -6992448646407690164L;  
  4.     /**讀鎖*/
  5.     privatefinal ReentrantReadWriteLock.ReadLock readerLock;  
  6.     /** 寫鎖 */
  7.     privatefinal ReentrantReadWriteLock.WriteLock writerLock;  
  8. 相關推薦

    JAVA 併發程式設計-基於執行緒池設計的ScheduledExecutor

        上篇部落格《JAVA 併發程式設計-執行緒池(七)》中曾介紹到newScheduledThreadPool(intcorePoolSize),建立corePoolSize大小的執行緒池。此執行緒池支援定時以及週期性執行任務的需求。    接下來我們一起來分析一下Jav

    Java併發程式設計技術內幕:聊聊技術內幕

          摘要:本文主要講了讀寫鎖。 一、讀寫鎖ReadWriteLock        在上文中回顧了併發包中的可重入鎖ReentrantLock,並且也分析了它的原始碼。從中我們知道它是一個單一鎖(筆者自創概念),意思是在多人讀、多人寫、或同時有人讀和寫時。只能有一個人能拿到鎖,執行

    Java併發程式設計技術內幕:Callable、Future、FutureTask、CompletionService

             在上一文章中,筆者介紹了執行緒池及其內部的原理。今天主要講的也是和執行緒相關的內容。一般情況下,使用Runnable介面、Thread實現的執行緒我們都是無法返回結果的。但是如果對一些場合需要執行緒返回的結果。就要使用用Callable、Future、Fut

    Java併發程式設計技術內幕:ForkJoin 框架初探

     一、ForkJoin介紹      ForkJoin是Java7提供的原生多執行緒並行處理框架,其基本思想是將大人物分割成小任務,最後將小任務聚合起來得到結果。它非常類似於HADOOP提供的MapReduce框架,只是MapReduce的任務可以針對叢集內的所有計算節點,

    Java併發程式設計技術內幕:ConcurrentHashMap原始碼解析

           摘要:本文主要講了Java中ConcurrentHashMap 的原始碼       ConcurrentHashMap 是java併發包中非常有用的一個類,在高併發場景用得非常多,它是執行緒安全的。要注意到雖然HashTable雖然也是執行緒安全的,但是它的效

    Java併發程式設計技術內幕:ThreadFactory、ThreadLocal

           摘要:本文主要講了ThreadFactory、ThreadLocal的例項和原始碼解析一、ThreadFactory1.1 原始碼解讀ThreadFactory這個故名思義,就是一個執行緒工廠。用來建立執行緒。這裡為什麼要使用執行緒工廠呢?其實就是為了統一在建立

    Java併發程式設計系列之四:volatile的記憶體語義

    前言 在前面的文章中已經提到過volatile關鍵字的底層實現原理:處理器的LOCK指令會使得其他處理器將快取重新整理到記憶體中(確切說是主存)以及會把其他處理器的快取設定為無效。這裡的記憶體語義則說的是在JMM中的實現,那麼為什麼要理解volatile和鎖在

    Java併發程式設計:執行緒和的使用解析

    執行緒的使用   新建執行緒   新建一個執行緒有兩種方法:繼承Thread類,然後重寫run方法;實現Runnable介面,然後實現run方法。實際上Thread類也是實現的Runnable介面,再加上類只能單繼承,所以推薦使用Runnable介面。示例如下:   class Demo

    Java併發程式設計:可重入

    關於執行緒安全的例子,簡而言之就是多個執行緒在同時訪問或修改公共資源的時候,由於不同執行緒搶佔公共資源而導致的結果不確定性,就是在併發程式設計中經常要考慮的執行緒安全問題。現在嘗試來用Lock顯式加鎖來解決執行緒安全的問題,先來看一下Lock介面的定義: public interface L

    java併發程式設計實戰之理解顯示ReentrantLock

    前面兩篇部落格分別介紹了通過synchronized關鍵字(內建鎖機制)和volatile關鍵字實現同步機制。由於volatile實現的同步不能保證操作的原子性,因此一般常用內建鎖實現同步機制,但java5.0版本的內建鎖在功能上有很多缺陷:如無法中斷一個正在等

    十五java併發程式設計--執行緒的死(deadlock)

    執行緒在作業系統使用不同的資源,一般以以下方式使用這些資源。 1)請求一個資源。 2)使用這個資源。 3)釋放資源。 1、什麼是死鎖? 死鎖的情況是,一些執行緒被阻塞,每個執行緒都擁有一個資源,並且等待另外一個程序以獲取另外的一個資源。 想了想

    十六java併發程式設計--執行緒的死解決方案(生產者和消費者幾種實現方式)

    上一篇中,主要了解了什麼時候死鎖,並且提出死鎖的一個解決方案,多個鎖要按照一定的順序來。 本片主要是利用生產者消費者模式解決執行緒的死鎖。 多執行緒生產者和消費者一個典型的多執行緒程式。一個生產者生產提供消費的東西,但是生產速度和消費速度是不同的。這就需要讓

    長文慎入-探索Java併發程式設計併發解決方案[轉]

    轉自:https://yq.aliyun.com/articles/636038 所有示例程式碼,請見/下載於https://github.com/Wasabi1234/concurrency   高併發處理的思路及手段    

    Java併發程式設計實踐筆記之——加機制(Locking)

    多個狀態變數的一致性保持 當執行緒安全的不變性條件中涉及多個變數時,並且各個變數之間不是彼此獨立,某個變數對其他變數的值產生約束。那當更新一個變數時,要在同一個原子操作中更新其他的變數內建鎖(Intrinsic Locks) Java提供了同步程式碼塊(Synchroni

    Java併發程式設計併發解決方案解析

    本文轉載自:Java併發程式設計與高併發解決方案解析 現在在各大網際網路公司中,隨著日益增長的網際網路服務需求,高併發處理已經是一個非常常見的問題,在這篇文章裡面我們重點討論兩個方面的問題,一是併發程式設計,二是高併發解決方案。 文章中的程式碼實現詳見 專案 Git

    2019最新Java併發程式設計併發解決教程

    併發: 同時擁有兩個或者多個執行緒,如果程式在單核處理器上執行多個執行緒將交替地換入或者換出記憶體,這些執行緒是 同時“存在”的,每個執行緒都處於執行過程中的某個狀態,如果執行在多核處理器上,此時,程式中的每個執行緒都 將分配到一個處理器核上,因此可以同時執行。高併發( Hi

    java併發程式設計——四(synchronized\Lock\volatile) 機制原理及關聯

    前言 其實標題使用互斥機制更合適,併發中主要兩個問題是:執行緒如何同步以及執行緒如何通訊。 同步主要是通過互斥機制保證的,而互斥機制我們最熟悉的就是鎖,當然也有無鎖的CAS實現。 多執行緒共享資源,比如一個物件的記憶體,怎樣保證多個執行緒不會同時訪問(讀取

    Java併發程式設計系列(二)-synchronized同步

    synchronized基本用法 從一個簡單的例子入手 1 public class C1 { 2 private int count = 10; 3 4 public void foo() { 5 count--; 6 System.out.p

    Java併發程式設計】之八:多執行緒環境安全使用集合API含程式碼

    在集合API中,最初設計的Vector和Hashtable是多執行緒安全的。例如:對於Vector來說,用來新增和刪除元素的方法是同步的。如果只有一個執行緒與Vector的例項互動,那麼,要求獲取

    阿里p8架構師分享:Java經典基礎高階面試36題和答案

    19.為什麼集合類沒有實現Cloneable和Serializable介面? 克隆(cloning)或者是序列化(serialization)的語義和含義是跟具體的實現相關的。因此,應該由集合類的具體實現來決定如何被克隆或者是序列化。 20.什麼是迭代器(Iterator)? Itera