资讯专栏INFORMATION COLUMN

Java多线程基础(八)——Read-Write Lock模式

snifes / 1687人阅读

摘要:二模式案例类数据类可以被多个线程同时访问。共享资源参与者代表和所共享的资源对象,提供不改变内部状态的操作,以及会改变内部状态的操作。读写锁参与者提供了对参与者进行操作和操作时需要的锁定。

一、定义

Read-Write Lock Pattern将读取与写入分开处理,在读取数据之前必须获取用来读取的锁定,而写入的时候必须获取用来写入的锁定。因为读取时实例的状态不会改变,所以多个线程可以同时读取;但是,写入会改变实例的状态,所以当有一个线程写入的时候,其它线程既不能读取与不能写入。

二、模式案例

Data类:
数据类可以被多个线程同时访问。

public class Data {
    private final char[] buffer;
    private final ReadWriteLock lock = new ReadWriteLock();
    public Data(int size) {
        this.buffer = new char[size];
        for (int i = 0; i < buffer.length; i++) {
            buffer[i] = "*";
        }
    }
    public char[] read() throws InterruptedException {
        lock.readLock();
        try {
            return doRead();
        } finally {
            lock.readUnlock();
        }
    }
    public void write(char c) throws InterruptedException {
        lock.writeLock();
        try {
            doWrite(c);
        } finally {
            lock.writeUnlock();
        }
    }
    private char[] doRead() {
        char[] newbuf = new char[buffer.length];
        for (int i = 0; i < buffer.length; i++) {
            newbuf[i] = buffer[i];
        }
        slowly();
        return newbuf;
    }
    private void doWrite(char c) {
        for (int i = 0; i < buffer.length; i++) {
            buffer[i] = c;
            slowly();
        }
    }
    private void slowly() {
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
        }
    }
}

WriterThread类:

public class WriterThread extends Thread {
    private static final Random random = new Random();
    private final Data data;
    private final String filler;
    private int index = 0;
    public WriterThread(Data data, String filler) {
        this.data = data;
        this.filler = filler;
    }
    public void run() {
        try {
            while (true) {
                char c = nextchar();
                data.write(c);
                Thread.sleep(random.nextInt(3000));
            }
        } catch (InterruptedException e) {
        }
    }
    private char nextchar() {
        char c = filler.charAt(index);
        index++;
        if (index >= filler.length()) {
            index = 0;
        }
        return c;
    }
}

ReaderThread类:

public class ReaderThread extends Thread {
    private final Data data;
    public ReaderThread(Data data) {
        this.data = data;
    }
    public void run() {
        try {
            while (true) {
                char[] readbuf = data.read();
                System.out.println(Thread.currentThread().getName() + " reads " + String.valueOf(readbuf));
            }
        } catch (InterruptedException e) {
        }
    }
}

ReadWriteLock类:
读写锁需要防止以下两类冲突:

“读取”和“写入”的冲突(read-write conflict)

“写入”和“写入”的冲突(write-write conflict)

注意:“读取”和“读取”之间不会冲突*

public final class ReadWriteLock {
    private int readingReaders = 0;        //正在读取线程的数量 
    private int writingWriters = 0;     //正在写入线程的数量
    public synchronized void readLock() throws InterruptedException {
        while (writingWriters > 0 ) {
            wait();
        }
        readingReaders++;                      
    }
    public synchronized void readUnlock() {
        readingReaders--;   
        notifyAll();
    }
    public synchronized void writeLock() throws InterruptedException {
        while (readingReaders > 0 || writingWriters > 0) {
            wait();
        }
        writingWriters++;                       
    }
    public synchronized void writeUnlock() {
        writingWriters--;     
        notifyAll();
    }
}

执行:

public class Main {
    public static void main(String[] args) {
        Data data = new Data(10);
        new ReaderThread(data).start();
        new ReaderThread(data).start();
        new ReaderThread(data).start();
        new ReaderThread(data).start();
        new ReaderThread(data).start();
        new ReaderThread(data).start();
        new WriterThread(data, "ABCDEFGHIJKLMNOPQRSTUVWXYZ").start();
        new WriterThread(data, "abcdefghijklmnopqrstuvwxyz").start();
    }
}
三、模式讲解

Read-Write Lock模式的角色如下:

Reader(读取者)参与者

Reader参与者会对SharedResource进行读。

Writer(写入者)参与者

Writer参与者会对SharedResource进行写。

SharedResource(共享资源)参与者

SharedResource代表Reader和Writer所共享的资源对象,SharedResource提供不改变内部状态的read操作,以及会改变内部状态的write操作。

ReadWriteLock(读写锁)参与者

ReadWriteLock提供了对SharedResource参与者进行read操作和write操作时需要的锁定。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/71513.html

相关文章

  • 并发中的锁文件模式

    摘要:序并发中的锁文件模式是企业设计模式中的一种。可以是本地锁,也可以分布式锁,看文件系统是本地还是分布式的,算是一种比较古老的方式。代码是原子操作要点检查文件如果不存在则创建,要是原子操作,使用即可实现锁占用过长怎么处理或者忘记解锁怎么处理 序 并发中的锁文件模式是Java企业设计模式中的一种。可以是本地锁,也可以分布式锁,看文件系统是本地还是分布式的,算是一种比较古老的方式。利用zk实现...

    weknow619 评论0 收藏0
  • Java线程进阶()—— J.U.C之locks框架:AQS的Conditon等待(3)

    摘要:关于接口的介绍,可以参见多线程进阶二锁框架接口。最终线程释放了锁,并进入阻塞状态。当线程被通知唤醒时,则是将条件队列中的结点转换成等待队列中的结点,之后的处理就和独占功能完全一样。 showImg(https://segmentfault.com/img/remote/1460000016012490); 本文首发于一世流云的专栏:https://segmentfault.com/bl...

    ityouknow 评论0 收藏0
  • 浅谈Java并发编程系列()—— LockSupport原理剖析

    摘要:此对象在线程受阻塞时被记录,以允许监视工具和诊断工具确定线程受阻塞的原因。阻塞当前线程,最长不超过纳秒,返回条件在的基础上增加了超时返回。唤醒线程唤醒处于阻塞状态的线程。 LockSupport 用法简介 LockSupport 和 CAS 是Java并发包中很多并发工具控制机制的基础,它们底层其实都是依赖Unsafe实现。 LockSupport是用来创建锁和其他同步类的基本线程阻塞...

    jeyhan 评论0 收藏0
  • Java并发】Java并发编程与高并发基础概念

    摘要:笔记来源并发编程与高并发解决方案并发基础综述多级缓存缓存一致性乱序执行优化内存模型规定抽象结构同步八种操作及规则并发的优势与风险并发与高并发基本概念基本概念并发同时拥有两个或者多个线程,如果程序在单核处理器上运行,多个线程将交替地换入或者换 笔记来源:【IMOOC】Java并发编程与高并发解决方案 并发基础 综述: CPU多级缓存:缓存一致性、乱序执行优化 Java内存模型:JM...

    stackfing 评论0 收藏0
  • 你和阿里资深架构师之间,差的不仅仅是年龄(进阶必看)

    摘要:导读阅读本文需要有足够的时间,笔者会由浅到深带你一步一步了解一个资深架构师所要掌握的各类知识点,你也可以按照文章中所列的知识体系对比自身,对自己进行查漏补缺,觉得本文对你有帮助的话,可以点赞关注一下。目录一基础篇二进阶篇三高级篇四架构篇五扩 导读:阅读本文需要有足够的时间,笔者会由浅到深带你一步一步了解一个资深架构师所要掌握的各类知识点,你也可以按照文章中所列的知识体系对比自身,对自己...

    huaixiaoz 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<