阿里巴巴面試之利用兩個int值實現讀寫鎖

首先咱們對讀寫鎖作一個概述:面試

假設你的程序中涉及到對一些共享資源的讀和寫操做,且寫操做沒有讀操做那麼頻繁。在沒有寫操做的時候,兩個線程同時讀一個資源沒有任何問題,因此應該容許多個線程能在同時讀取共享資源。可是若是有一個線程想去寫這些共享資源,就不該該再有其它線程對該資源進行讀或寫,也就是說:讀-讀能共存,讀-寫不能共存,寫-寫不能共存。這就須要一個讀/寫鎖來解決這個問題。併發

阿里巴巴四面最後的問題就涉及到了讀寫鎖的實現。ide

問:對JAVA中的讀寫鎖熟悉嗎?this

我:還能夠...spa

問:簡單介紹一下...線程

我:這是JAVA中的集合類,ReentrantReadWriteLock,分別處理讀與寫的操做,讀讀能夠共存,讀寫不能共存,寫寫不能共存...code

問:你本身實現一個讀寫鎖blog

我:用synchronized,用一個隊列...隊列

問:不能那麼麻煩,就用兩個int值資源

我:兩個int值,那必定是一個標記讀次數,一個標記寫次數啊,因而想了一會我想出瞭如下答案:

問:你這個能夠是能夠,可是若是讀操做大量的話,寫操做會產生飢餓等待...如何改進?

我想了想,是哦,而後腦子就短路了,掙扎,再掙扎...

我:給寫加上優先級

問:不能夠,就兩個int

我:讀次數設置一個閾值,超出主動釋放

問:不能夠,就兩個int

我一臉懵逼...腦補畫面

問:提醒你一下,lockwrite那裏改一下

面試官發音不標準,我聽了個lockread,想了半天,實在不知道怎麼改,隨便說了一個

問:我讓你改lockwrite...

我:額,我看看...

又是漫長的等待...

我:沒想出來...

問:把你那個條件拆開,讓寫佔個坑...

我恍然大悟,我去...

而後他大概說了一遍,就草草結束了,鬱悶中...

應該改爲:

回來以後,大概看了一下,把整個程序寫了一下:

package com.darrenchan.lock;

/**
 * 用兩個int變量實現讀寫鎖
 * @author Think
 *
 */
public class MyReadWriteLock {
    
    private int readcount = 0;
    private int writecount = 0;
    
    public void lockread() throws InterruptedException{
        while(writecount > 0){
            synchronized(this){
                wait();
            }
        }
        readcount++;
        //進行讀取操做
        System.out.println("讀操做");
    }
    
    public void unlockread(){
        readcount--;
        synchronized(this){
            notifyAll();
        }
    }
    
    public void lockwrite() throws InterruptedException{
        while(writecount > 0){
            synchronized(this){
                wait();
            }
        }
        //之因此在這裏先++,是先佔一個坑,避免讀操做太多,從而產生寫的飢餓等待
        writecount++;
        while(readcount > 0){
            synchronized(this){
                wait();
            }
        }
        //進行寫入操做
        System.out.println("寫操做");
    }
    
    public void unlockwrite(){
        writecount--;
        synchronized(this){
            notifyAll();
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        MyReadWriteLock readWriteLock = new MyReadWriteLock();
        for(int i = 0; i < 2; i++){
            Thread2 thread2 = new Thread2(i, readWriteLock);
            thread2.start();
        }
        
        for (int i = 0; i < 10; i++) {
            Thread1 thread1 = new Thread1(i, readWriteLock);
            thread1.start();
        }
        
    }

}

class Thread1 extends Thread{
    public int i;
    public MyReadWriteLock readWriteLock;
    
    public Thread1(int i, MyReadWriteLock readWriteLock) {
        this.i = i;
        this.readWriteLock = readWriteLock;
    }

    @Override
    public void run() {
        try {
            readWriteLock.lockread();
            Thread.sleep(1000);//模擬耗時
            System.out.println("第"+i+"個讀任務");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            readWriteLock.unlockread();
        }
    }
}


class Thread2 extends Thread{
    public int i;
    public MyReadWriteLock readWriteLock;
    
    public Thread2(int i, MyReadWriteLock readWriteLock) {
        this.i = i;
        this.readWriteLock = readWriteLock;
    }

    @Override
    public void run() {
        try {
            readWriteLock.lockwrite();
            Thread.sleep(1000);
            System.out.println("第"+i+"個寫任務");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            readWriteLock.unlockwrite();
        }
    }
}

 

執行結果:

寫操做
第0個寫任務
讀操做
讀操做
讀操做
讀操做
讀操做
讀操做
讀操做
讀操做
讀操做
讀操做
第9個讀任務
第3個讀任務
第1個讀任務
第8個讀任務
第2個讀任務
第0個讀任務
第7個讀任務
第4個讀任務
第5個讀任務
第6個讀任務
寫操做
第1個寫任務

 

固然這是簡單的,還能夠進一步加深,能夠參考博客:http://ifeve.com/read-write-locks/#simple

注:以上代碼在++和--的時候仍然會產生併發異常,建議用AtomicInteger類型,在硬件上保證++和--操做不會出現併發異常。

相關文章
相關標籤/搜索