多线程---读者写者问题

有几种思路

1、利用信号量来实现读者写者的互斥(读者和读者之间是并行的)

public class ReaderAndWriter
{
    private static  AtomicInteger reader = new AtomicInteger();
    private static  AtomicInteger blocked = new AtomicInteger();

    //用来对读者写者互斥
    private static Semaphore ws = new Semaphore(1,true);

    public static void main(String[] args)
    {
        System.out.println("Hello World!");
        ExecutorService executors = Executors.newFixedThreadPool(5);
        executors.execute(new Writerr());
        executors.execute(new Readerr(1));
        executors.execute(new Readerr(2));
        executors.execute(new Readerr(3));
        executors.execute(new Readerr(4));
        executors.shutdown();
    }
    static class Writerr implements Runnable
    {
        public void run(){
            try{
                while(true){
                    ws.acquire();
                    write();
                    //System.out.println("正在等待:" + ws.getQueueLength()+"-------"+blocked.get());
                    ws.release(blocked.get()==0 ? 1: blocked.get());
                    blocked.set(0);
                }
            }catch(InterruptedException ex){

            }
        }
        private static void write(){
            try{
                System.out.println("writing...");
                Thread.sleep((new Random().nextInt(2))*1000);
                System.out.println("writed!");
            }catch(InterruptedException ex){

            }
        }
    }
    static class Readerr implements Runnable
    {
        private int id;
        public Readerr(int id){
            this.id = id;
        }
        public void run(){
            try{
                while(true){
                    if(reader.get() == 0){
                        blocked.getAndIncrement();
                        ws.acquire();
                    }
                    //以原子方式将当前值加 1
                    reader.getAndIncrement();
                    read();
                    //以原子方式将当前值减 1
                    reader.getAndDecrement();
                    if(reader.get() == 0){
                        ws.release();
                    }
                    //出让时间,不与writer过度竞争
                    //System.out.println("["+id+"]出让时间");
                    Thread.sleep(6000);
                }
            }catch(InterruptedException ex){

            }
        }
        private void read(){
            try{
                System.out.println("["+id + "]reading...");
                Thread.sleep((new Random().nextInt(10))*1000);
                System.out.println("["+id+"]read!");
            }catch(InterruptedException ex){

            }
        }
    }
}

2、利用synchronized对实现读者写者互斥

    public class ReaderAndWriter1
{
    public static FILE file = new FILE();

    public static void main(String[] args)
    {
        System.out.println("Hello World!");
        ExecutorService executors = Executors.newFixedThreadPool(5);
        executors.execute(new Writerr());
        executors.execute(new Readerr(1));
        executors.execute(new Readerr(2));
        executors.execute(new Readerr(3));
        executors.execute(new Readerr(4));
        executors.shutdown();
    }
    static class Writerr implements Runnable
    {
        public void run(){
            while(true){
                file.write();
            }
        }

    }
    static class Readerr implements Runnable
    {
        private int id;
        public Readerr(int id){
            this.id = id;
        }
        public void run(){
            try{
                while(true){
                    file.read(id);
                    //出让时间,不与writer过度竞争
                    //System.out.println("["+id+"]出让时间");
                    Thread.sleep(6000);
                }
            }catch(InterruptedException ex){

            }
        }
    }
}

class FILE
{
    //读者数
    private static AtomicInteger reader = new AtomicInteger(0);
    //写者数
    private static AtomicInteger writer = new AtomicInteger(0);
    //写文件
    public void write(){
        try{
            synchronized(reader){
                if(reader.get() > 0)
                {
                    reader.wait();
                }
            }
            synchronized(writer){
                writer.getAndIncrement();
                System.out.println("writing...");
                Thread.sleep((new Random().nextInt(2))*1000);
                System.out.println("writed!");
                writer.getAndDecrement();
                writer.notifyAll();
            }
        }catch(InterruptedException ex){

        }
    }
    //读文件
    public void read(int id){
        try{
            synchronized(writer){
                if(writer.get() > 0){
                    writer.wait();
                }
            }
            reader.getAndIncrement();
            System.out.println("["+id + "]reading...");
            Thread.sleep((new Random().nextInt(10))*1000);
            System.out.println("["+id+"]read!");
            reader.getAndDecrement();
            synchronized(reader){
                if(reader.get() == 0){
                    reader.notify();
                }
            }
        }catch(InterruptedException ex){

        }
    }
}

3、concurrent包中提供了读者写者锁

ReadWriteLock 维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。只要没有 writer,读取锁可以由多个 reader 线程同时保持。写入锁是独占的。

Lock readLock() 返回用于读取操作的锁。

Lock writeLock() 返回用于写入操作的锁

//很简洁的程序
public class ReaderAndWriter2
{
    public static FILE file = new FILE();

    public static void main(String[] args)
    {
        System.out.println("Hello World!");
        ExecutorService executors = Executors.newFixedThreadPool(5);
        executors.execute(new Writerr());
        executors.execute(new Readerr(1));
        executors.execute(new Readerr(2));
        executors.execute(new Readerr(3));
        executors.execute(new Readerr(4));
        executors.shutdown();
    }
    static class Writerr implements Runnable
    {
        public void run(){
            while(true){
                file.write();
            }
        }

    }
    static class Readerr implements Runnable
    {
        private int id;
        public Readerr(int id){
            this.id = id;
        }
        public void run(){
            try{
                while(true){
                    file.read(id);
                    //出让时间,不与writer过度竞争
                    //System.out.println("["+id+"]出让时间");
                    Thread.sleep(6000);
                }
            }catch(InterruptedException ex){

            }
        }
    }

}

//文件类
class FILE
{
    //利用concurrent工具包中的读写锁
    private static ReadWriteLock lock = new ReentrantReadWriteLock();
    //写锁
    private static Lock write = lock.writeLock();
    //读锁
    private static Lock read = lock.readLock();
    //写操作
    public static void write(){
        try{
            write.lock();
            System.out.println("writing....");
            Thread.sleep(new Random().nextInt(3)*1000);
            System.out.println("writed!");
        }catch(InterruptedException ex){

        }finally{
            write.unlock();
        }
    }
    //读操作
    public static void read(int id){
        try{
            read.lock();
            System.out.println("["+id+"]reading....");
            Thread.sleep(new Random().nextInt(5)*1000);
            System.out.println("["+id+"]read!");
            //出让时间
            Thread.sleep(6000);
        }catch(InterruptedException ex){

        }finally{
            read.unlock();
        }
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 22:48:23

多线程---读者写者问题的相关文章

多线程读者写者问题--用QT实现

先把代码贴上来,有时间再整理吧..因为工作中用Qt,所以用Qt实现的....刚上班,,忙! 三种方法,读者优先,写者优先和公平竞争.. 读者优先 #include <QCoreApplication> #include <QThread> #include <iostream> #include <QMutex> #include <QTime> #include <QtGlobal> using namespace std; int

秒杀多线程第十一篇 读者写者问题

与上一篇<秒杀多线程第十篇 生产者消费者问题>的生产者消费者问题一样,读者写者也是一个非常著名的同步问题.读者写者问题描述非常简单,有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者在读文件时写者也不去能写文件. 上面是读者写者问题示意图,类似于生产者消费者问题的分析过程,首先来找找哪些是属于“等待”情况. 第一.写者要等到没有读者时才能去写文件. 第二.所有读者要等待写者完成写文件后才能去读文件. 找完“等待”情况后,再看看有没有要互斥访问的资源.由

转---秒杀多线程第十一篇 读者写者问题

与上一篇<秒杀多线程第十篇 生产者消费者问题>的生产者消费者问题一样,读者写者也是一个非常著名的同步问题.读者写者问题描述非常简单,有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者在读文件时写者也不去能写文件. 上面是读者写者问题示意图,类似于生产者消费者问题的分析过程,首先来找找哪些是属于“等待”情况. 第一.写者要等到没有读者时才能去写文件. 第二.所有读者要等待写者完成写文件后才能去读文件. 找完“等待”情况后,再看看有没有要互斥访问的资源.由

转---秒杀多线程第十四篇 读者写者问题继 读写锁SRWLock

在<秒杀多线程第十一篇读者写者问题>文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法——读写锁SRWLock来解决这一问题.读 写锁在对资源进行保护的同时,还能区分想要读取资源值的线程(读取者线程)和想要更新资源的线程(写入者线程).对于读取者线程,读写锁会允许他们并发的 执行.当有写入者线程在占有资源时,读写锁会让其它写入者线程和读取者线程等待.因此用读写锁来解决读者写者问题会使代码非常清晰和简洁. 下面就来看看如何使用读

Linux多线程实践(6) --Posix读写锁解决读者写者问题

Posix读写锁 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_wrlock(pthre

多线程面试题系列(14):读者写者问题继 读写锁SRWLock

在第十一篇文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法--读写锁SRWLock来解决这一问题.读写锁在对资源进行保护的同时,还能区分想要读取资源值的线程(读取者线程)和想要更新资源的线程(写入者线程).对于读取者线程,读写锁会允许他们并发的执行.当有写入者线程在占有资源时,读写锁会让其它写入者线程和读取者线程等待.因此用读写锁来解决读者写者问题会使代码非常清晰和简洁. 下面就来看看如何使用读写锁,要注意编译读写锁程序需要V

秒杀多线程第十一篇 读者写者问题(续)

java实现: 本问题的关键是读者写者之间的同步问题,尤其使用java来操作. 1.等待读者,使用CountDownLatch mReaderLatch, 但是CountDownLatch只能使用一次,所以需要每次都new 一个. 或者可以考虑使用semaphore代替,但是semaphore需要acquire(READ_THREAD_SIZE)才能等待所有读者线程结束. 2.等待写入操作.使用semaphore来控制, mWriteSema.release(READ_THREAD_SIZE);

读者写者模式

在编写多线程的时候,有一种情况是比较常见的.那就是,有些公共数据修改的机会比较少.相较改写,它们读的机会反而多的多. 读者写者模式:三种关系,两类人,一个场所 三种关系: 读者与读者:无关系 写者与写者:互斥 读者与写者:同步与互斥 两类人:读者,写者 一个场所:同一临界资源(数据) 自旋锁:如果所等待条件不满足,不挂起,一直申请锁.适宜某个线程占用锁时间较短. 当不断有多个读者准备读时,如果有写者到来,此时应该当前读者读完后,提高写者优先级,下个进入临界区的是写者.---------写者优先,

Java实现生产者消费者问题与读者写者问题

摘要: Java实现生产者消费者问题与读者写者问题 1.生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品.解决生产者/消费者问题的方法可分为两类:(1)采用某种机制保护生产者和消费者之间的同步:(2)在生产者和消费者之间建立一个管道.第一种方式有较高的效率,并且易于实现,代码的可控制性较好,属于常用的模式.第二种管道缓冲区不易控制,被传输数据对象不易于封装等,实用性不强. 同步问题核心在