博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
阿里巴巴面试之利用两个int值实现读写锁
阅读量:5318 次
发布时间:2019-06-14

本文共 3565 字,大约阅读时间需要 11 分钟。

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

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

阿里巴巴四面最后的问题就涉及到了读写锁的实现。

问:对JAVA中的读写锁熟悉吗?

我:还可以...

问:简单介绍一下...

我:这是JAVA中的集合类,ReentrantReadWriteLock,分别处理读与写的操作,读读可以共存,读写不能共存,写写不能共存...

问:你自己实现一个读写锁

我:用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个写任务

 

当然这是简单的,还可以进一步加深,可以参考博客:

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

转载于:https://www.cnblogs.com/DarrenChan/p/8619476.html

你可能感兴趣的文章
android菜鸟学习笔记5----第一个android程序
查看>>
2.5 非透明PCI桥 分类: 浅谈PCI 2...
查看>>
POJ 2263 Heavy Cargo(Floyd + map)
查看>>
Macbook pro 下修改MySQL数据库密码
查看>>
使用postman做接口测试(一)
查看>>
Linux的locale、LC_ALL和LANG
查看>>
C# 动态调用DLL库
查看>>
Ubuntu使用问题解决办法
查看>>
android 开发 实现RecyclerView的列表单选功能
查看>>
从零教你如何获取hadoop2.4源码并使用eclipse关联hadoop2.4源码
查看>>
超详细单机版搭建hadoop环境图文解析
查看>>
P2P UPD打洞原理
查看>>
Unity3D使用小技巧
查看>>
播放器设置 Player Settings
查看>>
IntelliJ IDEA添加JUnit单元测试
查看>>
循环群
查看>>
python 函数的应用、闭包、迭代器
查看>>
mysql数据库学习记录1
查看>>
nodejs-mysql模块
查看>>
HDU--2546 饭卡
查看>>