1. 程式人生 > 其它 >Java執行緒學習之讀寫鎖

Java執行緒學習之讀寫鎖

讀寫鎖:

  因為讀寫鎖分為讀鎖和寫鎖,讀因為不會對資料造成改變,所以兩個或多個執行緒的讀之間不需要新增鎖。而寫鎖不同,因為寫對資料會進行改變,所以 寫與寫之間,讀與寫之間都需要加鎖控制。而在重入鎖中,讀與讀之間也會使用互斥鎖,造成等待時間延長。這樣的話讀寫鎖的使用場景也就出來了,讀寫鎖適用於讀操作遠比寫操作的次數,這樣可以提升系統性能。

例子:

package com.example.demo.bingfa;

import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockDemo {
    public static Lock lock = new ReentrantLock();
    public static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private static Lock readLock = readWriteLock.readLock();
    public static Lock writeLock = readWriteLock.writeLock();
    private int value;
    public static long readTime;
    public static  long writeTime;
    public static void main(String[] args) throws InterruptedException {
        final ReadWriteLockDemo demo = new ReadWriteLockDemo();
        Runnable readRunnale = new Runnable() {
            @Override
            public void run() {
                try {
                    //此處傳入的是讀鎖,如果換成重入鎖,執行結果會變化很大
                    demo.handleRead(readLock);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        Runnable writeRunnale = new Runnable() {
            @Override
            public void run() {
                try {
                    //此處傳入的是寫鎖,如果換成重入鎖,將會改變
                    demo.handleWrite(writeLock, new Random().nextInt());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        long start=System.currentTimeMillis();
        for (int i = 0; i < 10; i++) {
            new Thread(readRunnale).start();
        }
        for (int i = 10; i < 20; i++) {
                new Thread(writeRunnale).start();
        }
        //讓主執行緒等待一段時間,確保子執行緒均已執行完畢
        Thread.sleep(30000);
        System.out.println("讀操作耗時:" +(readTime-start)+"        寫操作耗時"+(writeTime-start));
    }

    /**
     * 寫操作處理,因為寫與寫之間是互斥的 ,所以每個寫的執行緒都需要等待獲得鎖
     * @param writeLock
     * @param i
     * @throws InterruptedException
     */
    private void handleWrite(Lock writeLock, int i) throws InterruptedException {
        try {
            writeLock.lock();
            Thread.sleep(1000);
            value = i;
        } finally {
            writeLock.unlock();
            writeTime=System.currentTimeMillis();
        }
    }

    /**
     * 因為讀與讀之間不是互斥的所以讀與讀是可以並行的
     * @param readLock
     * @return
     * @throws InterruptedException
     */
    private int handleRead(Lock readLock) throws InterruptedException {
        try {
            readLock.lock();
            Thread.sleep(1000);
            return value;
        } finally {

            readLock.unlock();
            readTime=System.currentTimeMillis();
        }
    }
}