首先咱們對讀寫鎖作一個概述:面試
假設你的程序中涉及到對一些共享資源的讀和寫操做,且寫操做沒有讀操做那麼頻繁。在沒有寫操做的時候,兩個線程同時讀一個資源沒有任何問題,因此應該容許多個線程能在同時讀取共享資源。可是若是有一個線程想去寫這些共享資源,就不該該再有其它線程對該資源進行讀或寫,也就是說:讀-讀能共存,讀-寫不能共存,寫-寫不能共存。這就須要一個讀/寫鎖來解決這個問題。併發
阿里巴巴四面最後的問題就涉及到了讀寫鎖的實現。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類型,在硬件上保證++和--操做不會出現併發異常。