鎖是啥我就很少BB了,各位在學習JUC前先簡單實現一個本身的讀寫鎖豈不美哉。web
/**
* 讀寫鎖
*/
public class ReadWriteLock {
private int readingReaders = 0; //正在讀的線程數
private int waitingReaders = 0; //正在等待鎖的讀線程數
private int writingWriters = 0; //正在寫的線程數
private int waitingWriters = 0; //正在等待鎖的寫線程數
private boolean readerFirst = true; //寫者優先
/**
* 無參構造,默認讀者優先
*/
public ReadWriteLock() {
this(true);
}
public ReadWriteLock(boolean preferReader) {
this.readerFirst = preferReader;
}
/**
* 讀鎖
*/
public synchronized void readLock() throws InterruptedException {
//有讀線程須要來獲取鎖,讀等待線程數量加1.
this.waitingReaders++;
try {
//若是有讀線程正在寫,則阻塞。不阻塞讀,到達讀讀無鎖的目的。
while (writingWriters > 0) {
this.wait();
}
//沒有寫線程正在寫,則能夠進行讀了,並將正在讀線程數量++。
this.readingReaders++;
}finally {
//等待讀線程數量--
this.waitingReaders--;
}
}
/**
* 讀解鎖
*/
public synchronized void readUnlock() {
//讀完成後,正在讀線程數量--
this.readingReaders--;
//喚醒全部被阻塞的線程,能被讀解鎖喚醒的阻塞線程必定是寫線程。
this.notifyAll();
}
/**
* 寫鎖
*/
public synchronized void writeLock() throws InterruptedException {
//有寫線程須要來獲取鎖,寫等待線程數量加1.
this.waitingWriters++;
try {
//若是有正在寫的線程 或 有正在讀的線程 或 有等待的讀線程(讀者優先),則當前寫線程阻塞。
while (writingWriters > 0 || readingReaders > 0 || (readerFirst && waitingReaders > 0)) {
this.wait();
}
//若是無,則能夠開始進行寫,正在寫線程數量++
this.writingWriters++;
} finally {
//等待讀線程數量--
this.waitingWriters--;
}
}
/**
* 寫解鎖
*/
public synchronized void writeUnlock() {
//寫完成後,正在寫線程數量--
this.writingWriters--;
//喚醒全部被阻塞的線程,讀寫皆有可能。
this.notifyAll();
}
public int getWaitingWriters(){
return waitingWriters;
}
public int getWaitingReaders(){
return waitingReaders;
}
}
複製代碼
上文代碼經過條件判斷統計參數以及阻塞的方式,實現了一個簡單的「讀寫」、「寫寫」互斥的鎖,可是「讀讀」不互斥。dom
若是寫線程獲取鎖以前有正在等待讀(以前有人正在寫,阻塞住了),那麼寫線程阻塞進行等待,優先讓給正在等待讀的線程。編輯器
注:若是想更改成寫者優先的話,能夠更改代碼,增長標誌位,或者是標誌位複用的方式,而且更改循環裏判斷條件便可。ide
/*
* 共享資源
**/
public class SharedData {
private String value;
private final ReadWriteLock lock = new ReadWriteLock();
public SharedData() {
value = "";
}
public String read() throws InterruptedException {
try {
lock.readLock();
System.out.println("正在寫等待的線程數量 :"+lock.getWaitingWriters());
System.out.println("正在讀等待的線程數量 :"+lock.getWaitingReaders());
System.out.println(Thread.currentThread().getName() + " 讀到了: " + this.value);
System.out.println("------------------------------------------------");
sleep(100);
return this.value;
} finally {
lock.readUnlock();
}
}
public void write(String s) throws InterruptedException {
try {
lock.writeLock();
System.out.println("正在寫等待的線程數量:"+lock.getWaitingReaders());
System.out.println("正在讀等待的線程數量 :"+lock.getWaitingReaders());
System.out.println(Thread.currentThread().getName() + " 寫了: " + s);
System.out.println("------------------------------------------------");
sleep(200);
this.value = s;
} finally {
lock.writeUnlock();
}
}
private void sleep(int ms) throws InterruptedException {
Thread.sleep(ms);
}
}
複製代碼
* 模擬讀線程
*/
public class ReaderWorker extends Thread {
private static final Random random = new Random(System.currentTimeMillis());
//共享資源
private final SharedData data;
public ReaderWorker(SharedData data) {
this.data = data;
}
@Override
public void run() {
try {
while (true) {
String s = data.read();
sleep(random.nextInt(1000));
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"被中斷了~");
return;
}
}
}
複製代碼
* 模擬寫線程
*/
public class WriterWorker extends Thread {
private static final Random random = new Random(System.currentTimeMillis());
private final SharedData data;
private String s;
public WriterWorker(SharedData data, String s) {
this.data = data;
this.s = s;
}
@Override
public void run() {
try {
while (true) {
data.write(s);
Thread.sleep(random.nextInt(1000));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
複製代碼
* 讀寫鎖test
*/
public class ReadWritLockClient {
public static void main(String[] args) {
final SharedData sharedData = new SharedData();
new ReaderWorker(sharedData).start();
new ReaderWorker(sharedData).start();
new WriterWorker(sharedData, "ABC").start();
new WriterWorker(sharedData, "DEF").start();
new WriterWorker(sharedData, "GHI").start();
new WriterWorker(sharedData, "JKL").start();
new WriterWorker(sharedData, "LMN").start();
}
}
複製代碼
模擬若干個讀寫線程進行共享資源競爭學習
不會出現「讀寫」、「寫寫」的狀況~ 完事flex
本文使用 mdnice 排版this