欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java并發(fā)編程之重入鎖與讀寫鎖

 更新時(shí)間:2017年09月25日 15:19:29   作者:麥田  
這篇文章主要介紹了Java并發(fā)編程之重入鎖與讀寫鎖,文中相關(guān)實(shí)例代碼詳細(xì),測試可用,具有一定參考價(jià)值,需要的朋友可以了解下。

重入鎖

重入鎖,顧名思義,就是支持重進(jìn)入的鎖,它表示該鎖能夠支持一個(gè)線程對資源的重復(fù)加鎖。重進(jìn)入是指任意線程在獲取到鎖之后能夠再次獲取該鎖而不會被鎖阻塞,該特性的實(shí)現(xiàn)需要解決以下兩個(gè)問題。

1、線程再次獲取鎖。鎖需要去識別獲取鎖的線程是否為當(dāng)前占據(jù)鎖的線程,如果是,則再次成功獲取。

2、鎖的最終釋放。線程重復(fù)n次獲取了鎖,隨后在第n次釋放該鎖后,其他線程能夠獲取到該鎖。鎖的最終釋放要求鎖對于獲取進(jìn)行計(jì)數(shù)自增,計(jì)數(shù)表示當(dāng)前鎖被重復(fù)獲取的次數(shù),而鎖被釋放時(shí),計(jì)數(shù)自減,當(dāng)計(jì)數(shù)等于0時(shí)表示鎖已經(jīng)成功釋放。

Java里面內(nèi)置鎖(synchronize)和Lock(ReentrantLock)都是可重入的

synchronized 實(shí)例

package com.home;
public class SynchronizedTest implements Runnable {
  public synchronized void method1() {
    System.out.println("method1獲得鎖,正常運(yùn)行!");
    method2();
  }
  public synchronized void method2() {
    System.out.println("method2獲得鎖,也正常運(yùn)行!");
  }
  @Override
  public void run() {
    method1();
  }
  public static void main(String[] args) {
    SynchronizedTest st = new SynchronizedTest();
    new Thread(st).start();
    new Thread(st).start();
  }
}

Lock 實(shí)例

package com.home;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest implements Runnable {
  Lock lock = new ReentrantLock();
  public void method1() {
    lock.lock();
    System.out.println("method1獲得鎖,正常運(yùn)行!");
    method2();
    lock.unlock();
  }
  public void method2() {
    lock.lock();
    System.out.println("method2獲得鎖,也正常運(yùn)行!");
    lock.unlock();
  }
  @Override
  public void run() {
    method1();
  }
  public static void main(String[] args) {
    LockTest lt = new LockTest();
    new Thread(lt).start();
    new Thread(lt).start();
  }
}

兩個(gè)例子最后的結(jié)果都是正確的,結(jié)果如下:

method1獲得鎖,正常運(yùn)行!
method2獲得鎖,也正常運(yùn)行!
method1獲得鎖,正常運(yùn)行!
method2獲得鎖,也正常運(yùn)行!

可重入鎖最大的作用是避免死鎖

讀寫鎖

讀寫鎖維護(hù)了一對相關(guān)的鎖,一個(gè)用于只讀操作,一個(gè)用于寫入操作。只要沒有writer,讀取鎖可以由多個(gè)reader線程同時(shí)保持。寫入鎖是獨(dú)占的。

可重入讀寫鎖 ReentrantReadWriteLock

ReentrantReadWriteLock對象提供了readLock()和writeLock()方法, 用于獲取讀取鎖和寫入鎖.

讀取鎖允許多個(gè)reader線程同時(shí)持有, 而寫入鎖最多只能有一個(gè)writter線程持有.

讀寫鎖的使用場合: 讀取共享數(shù)據(jù)的頻率遠(yuǎn)大于修改共享數(shù)據(jù)的頻率. 在上述場合下, 使用讀寫鎖控制共享資源的訪問, 可以提高并發(fā)性能.

如果一個(gè)線程已經(jīng)持有了寫入鎖, 則可以再持有讀寫鎖. 相反, 如果一個(gè)線程已經(jīng)持有了讀取鎖, 則在釋放該讀取鎖之前, 不能再持有寫入鎖.

可以調(diào)用寫入鎖的newCondition()方法獲取與該寫入鎖綁定的Condition對象, 此時(shí)與普通的互斥鎖并沒有什么區(qū)別. 但是調(diào)用讀取鎖的newCondition()方法將拋出異常.

例子

package com.home;
import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
class ReadWrte {
  // 共享數(shù)據(jù),可以多個(gè)線程讀數(shù)據(jù),只能有一個(gè)線程寫數(shù)據(jù)
  private int data;
  // 創(chuàng)建讀寫鎖
  ReadWriteLock rwLock = new ReentrantReadWriteLock();
  /**
   * 讀數(shù)據(jù),上讀鎖
   */
  public void get() {
    // 讀鎖
    rwLock.readLock().lock();
    try {
      System.out.println(Thread.currentThread().getName() + ",Read!");
      Thread.sleep((long) Math.random() * 1000);
      System.out.println(Thread.currentThread().getName() + " 讀出的數(shù)據(jù)為:" +
        this.getData());
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      rwLock.readLock().unlock();
    }
  }
  /**
   * 寫數(shù)據(jù),上寫鎖
   *
   * @param data
   */
  public void put(int data) {
    // 寫鎖
    rwLock.writeLock().lock();
    try {
      System.out.println(Thread.currentThread().getName() + ",Write!");
      Thread.sleep((long) Math.random() * 1000);
      this.setData(data);
      System.out.println(Thread.currentThread().getName() + " 寫入的數(shù)據(jù)為:" +
        this.getData());
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      rwLock.writeLock().unlock();
    }
  }
  public int getData() {
    return data;
  }
  public void setData(int data) {
    this.data = data;
  }
}
/**
 * 測試類
 *
 * @author itmyhome
 *
 */
public class ReadWriteLockTest {
  /**
   * @param args
   */
  public static void main(String[] args) {
    // 創(chuàng)建ReadWrte對象
    final ReadWrte rw = new ReadWrte();
    for (int i = 0; i < 10; i++) {
      // 創(chuàng)建并啟動10個(gè)讀線程
      new Thread(new Runnable() {
          @Override
          public void run() {
            rw.get();
          }
        }).start();
      // 創(chuàng)建并啟動10個(gè)寫線程
      new Thread(new Runnable() {
          @Override
          public void run() {
            // 寫入一個(gè)隨機(jī)數(shù)
            rw.put(new Random().nextInt(8));
          }
        }).start();
    }
  }
}

輸出為

Thread-0,Read!
Thread-4,Read!
Thread-8,Read!
Thread-12,Read!
Thread-0 讀出的數(shù)據(jù)為:0
Thread-4 讀出的數(shù)據(jù)為:0
Thread-8 讀出的數(shù)據(jù)為:0
Thread-12 讀出的數(shù)據(jù)為:0
Thread-19,Write!
Thread-19 寫入的數(shù)據(jù)為:5
Thread-7,Write!
Thread-7 寫入的數(shù)據(jù)為:7
Thread-3,Write!
Thread-3 寫入的數(shù)據(jù)為:4
Thread-16,Read!
Thread-16 讀出的數(shù)據(jù)為:4
Thread-11,Write!
Thread-11 寫入的數(shù)據(jù)為:0
Thread-15,Write!
Thread-15 寫入的數(shù)據(jù)為:5
Thread-2,Read!
Thread-2 讀出的數(shù)據(jù)為:5
Thread-17,Write!
Thread-17 寫入的數(shù)據(jù)為:2
Thread-6,Read!
Thread-6 讀出的數(shù)據(jù)為:2
Thread-1,Write!
Thread-1 寫入的數(shù)據(jù)為:5
Thread-13,Write!
Thread-13 寫入的數(shù)據(jù)為:4
Thread-9,Write!
Thread-9 寫入的數(shù)據(jù)為:7
Thread-5,Write!
Thread-5 寫入的數(shù)據(jù)為:2
Thread-10,Read!
Thread-10 讀出的數(shù)據(jù)為:2
Thread-18,Read!
Thread-14,Read!
Thread-18 讀出的數(shù)據(jù)為:2
Thread-14 讀出的數(shù)據(jù)為:2

從圖中我們可以看出,可以多個(gè)線程同時(shí)讀,但只能一個(gè)線程寫,即寫數(shù)據(jù)和寫入數(shù)據(jù)一并完成。

總結(jié)

以上就是本文關(guān)于Java并發(fā)編程之重入鎖與讀寫鎖的全部內(nèi)容,希望對大家有所幫助。歡迎各位參閱本站其他專題,有什么問題可以隨時(shí)留言,小編會及時(shí)回復(fù)大家的。感謝大家對本站的支持。

相關(guān)文章

  • mybatis實(shí)現(xiàn)mapper代理模式的方式

    mybatis實(shí)現(xiàn)mapper代理模式的方式

    本文向大家講解mybatis的mapper代理模式,以根據(jù)ide值查詢單條數(shù)據(jù)為例編寫xml文件,通過mapper代理的方式進(jìn)行講解增刪改查,分步驟給大家講解的很詳細(xì),對mybatis mapper代理模式相關(guān)知識感興趣的朋友一起看看吧
    2021-06-06
  • 微信APP支付(IOS手機(jī)端+java后臺)版

    微信APP支付(IOS手機(jī)端+java后臺)版

    這篇文章主要為大家詳細(xì)介紹了微信APP支付(IOS手機(jī)端+java后臺)版,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • Leetcode常見鏈表問題及代碼示例

    Leetcode常見鏈表問題及代碼示例

    這篇文章主要介紹了Leetcode常見鏈表問題及代碼示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • java數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)順序表示例

    java數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)順序表示例

    這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)順序表示例,需要的朋友可以參考下
    2014-03-03
  • java中BigDecimal用法詳解

    java中BigDecimal用法詳解

    本文詳細(xì)講解了java中BigDecimal的用法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • Java集合框架LinkedList詳解及實(shí)例

    Java集合框架LinkedList詳解及實(shí)例

    這篇文章主要介紹了Java集合框架LinkedList詳解及實(shí)例的相關(guān)資料,從定義,概述,用法進(jìn)行介紹,需要的朋友可以參考下
    2017-04-04
  • Springboot中使用lombok的@Data注解方式

    Springboot中使用lombok的@Data注解方式

    這篇文章主要介紹了Springboot中使用lombok的@Data注解方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 一步步教你把SpringBoot項(xiàng)目打包成Docker鏡像

    一步步教你把SpringBoot項(xiàng)目打包成Docker鏡像

    Docker可以讓開發(fā)者打包他們的應(yīng)用以及依賴包到一個(gè)輕量級、可移植的容器中,然后發(fā)布到任何流行的 Linux 機(jī)器上,也可以實(shí)現(xiàn)虛擬化,下面這篇文章主要給大家介紹了關(guān)于SpringBoot項(xiàng)目打包成Docker鏡像的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • ant打包jar文件腳本分享

    ant打包jar文件腳本分享

    本文介紹的ant腳本是用來打包jar文件,做完JAVA應(yīng)用一定會用到這個(gè),需要的朋友可以參考下
    2014-03-03
  • Java實(shí)現(xiàn)斷點(diǎn)下載服務(wù)端與客戶端的示例代碼

    Java實(shí)現(xiàn)斷點(diǎn)下載服務(wù)端與客戶端的示例代碼

    這篇文章主要為大家介紹了如何實(shí)現(xiàn)服務(wù)端(Spring Boot)與客戶端(Android)的斷點(diǎn)下載與下載續(xù)傳功能,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2022-08-08

最新評論