手写读写锁

Posted andrew520

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写读写锁相关的知识,希望对你有一定的参考价值。

https://www.cnblogs.com/DarrenChan/p/8619476.html

首先我们对读写锁做一个概述:

假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写,也就是说:读-读能共存,读-写不能共存,写-写不能共存。这就需要一个读/写锁来解决这个问题。

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();
        }
    }
}

  

当然这是简单的,还可以进一步加深,可以参考博客:http://ifeve.com/read-write-locks/#simple

注:以上代码在++和--的时候仍然会产生并发异常,建议用AtomicInteger类型,在硬件上保证++和--操作不会出现并发异常。

以上是关于手写读写锁的主要内容,如果未能解决你的问题,请参考以下文章

java中ReentrantReadWriteLock读写锁的使用

互斥锁自旋锁读写锁和条件变量

ReentrantReadWriteLock场景应用

手写数字识别——基于全连接层和MNIST数据集

前端面试题之手写promise

读写锁ReentrantReadWriteLock源代码浅析