(二)線程同步_5---使用read/write鎖同步數據

使用read/write鎖同步數據

在同步機制中,一個顯著的改進就是提供了ReadWriteLock接口和其實現類ReentrantReadWriteLock,該類有一對互斥鎖(mutual exclusion lock),一個是read lock,一個是write lock,在同一時刻能夠有多個讀線程或者在同一時刻只能有一個寫線程;當一個寫線程正在執行,全部的讀線程都將被阻塞,由於讀Lock和寫Lock是一對互斥的鎖;java

ReadWriteLock接口中哦那個有兩個方法:dom

  • Lock readLock();
  • Lock writeLock();

ReentrantReadWriteLock是該接口的惟一實現類;ide

下面一個例子是讀寫一個價格信息this

動手實現

(1)建立價格信息類spa

public class PricesInfo {
    private double priceA;
    private double priceB;

    private ReadWriteLock lock=new ReentrantReadWriteLock();

    public PricesInfo() {
        this(1.0, 2.0);
    }
    public PricesInfo(double priceA, double priceB) {
        this.priceA = priceA;
        this.priceB = priceB;
    }

    public double getPriceA() {
        lock.readLock().lock();
        System.out.printf("%s: PriceA readLock: lock\n",Thread.currentThread().getName());
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        double value=priceA;
        System.out.printf("%s: PriceA readLock: unlock\n",Thread.currentThread().getName());
        lock.readLock().unlock();

        return value;
    }

    public double getPriceB() {
        lock.readLock().lock();
        double value=priceB;
        lock.readLock().unlock();
        return value;
    }

    public void setPrices(double priceA, double priceB) {
        lock.writeLock().lock();
        System.out.printf("%s :Writer locked.\n",Thread.currentThread().getName());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.priceA=priceA;
        this.priceB=priceB;
        lock.writeLock().unlock();
        System.out.printf("%s :Writer unlock.\n", Thread.currentThread().getName());
    }
}
(2)建立讀線程

public class Reader implements Runnable{
    private PricesInfo pricesInfo;

    public Reader(PricesInfo pricesInfo) {
        this.pricesInfo = pricesInfo;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.printf("%s: Price B: %f\n",
                    Thread.currentThread().getName(),pricesInfo.getPriceB());
            System.out.printf("%s: Price A: %f\n",
                    Thread.currentThread().getName(),pricesInfo.getPriceA());
        }
    }
}

(3)建立寫線程
public class Writer implements Runnable {
    private PricesInfo pricesInfo;

    public Writer(PricesInfo pricesInfo) {
        this.pricesInfo = pricesInfo;
    }

    @Override
    public void run() {
        for (int i=0; i<3; i++) {
            System.out.printf("Writer: Attempt to modify the prices.\n");
            pricesInfo.setPrices(Math.random() * 10, Math.random() * 8);
            System.out.printf("Writer: Prices have been modified.\n");
            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
經過觀察輸出能夠看出:

  • 當沒有出現寫線程時,多個讀線程之間互不相干,正常讀取;
  • 只有當讀線程都釋放了鎖,寫線程才能執行,而且同一時刻只能執行一個;
  • 當寫線程執行時,讀線程都將阻塞;


要點

ReadWriteLock包含一對互斥鎖,當Read Lock被線程佔有時,Write Lock被阻塞;反之亦然;讀線程能夠有多個;
相關文章
相關標籤/搜索