带你实现一个你上你也行的读写锁

前言

锁是啥我就很少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();
}
}
}
复制代码
国际惯例主线程psvm
* 读写锁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

相关文章
相关标签/搜索