写者与读者问题

2022-05-14 22:07:34 多线程 编辑:黎为乐

信号量

package com.synchronous;

import java.util.Random;
import java.util.concurrent.Semaphore;
//读者可以同时读取数据库,只能有一个可以写数据库,读写操作不能同时进行
//读者优先
public class WriterAndReader{
    private Semaphore WriteMutex;
    private Semaphore CountMutex;   //维护Rcount
    private int Rcount=0;
    public WriterAndReader() {
        this.WriteMutex=new Semaphore(1);
        this.CountMutex=new Semaphore(1);
    }

    public void WriteDatabase() throws InterruptedException {
        int time=new Random().nextInt(2000);
        System.out.println("写入数据库操作"+time);
        Thread.sleep(time);
        System.out.println("写入数据库操作完成"+time);
    }
    public void ReadDatabase() throws InterruptedException {
        int time=new Random().nextInt(2000);
        System.out.println("读取数据库操作"+time);
        Thread.sleep(time);
        System.out.println("读取数据库操作完成"+time);
    }
    public void Writer() throws InterruptedException {
        WriteMutex.acquire();
        WriteDatabase();
        WriteMutex.release();
    }

    public void Reader() throws InterruptedException {
        CountMutex.acquire();   //Count上锁防止Rount被其他读操作更改
        if (Rcount==0)  //如果当前没有读操作
            WriteMutex.acquire();   //等待写操作完成
        ++Rcount;
        CountMutex.release();   //Count解锁
        ReadDatabase();
        --Rcount;
        if(Rcount==0)
            WriteMutex.release();   //如果没有读者,则唤醒写者
        CountMutex.release();
    }

    public static void main(String[] args) throws InterruptedException {
        int flag= 0;
        WriterAndReader writerAndReader = new WriterAndReader();
        for(int i=0;i<=20;i++){
            flag=new Random().nextInt(100);
            if (flag%3==0){
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        try {
                            writerAndReader.Writer();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
            else {
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        try {
                            writerAndReader.Reader();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }
    }
}


管程

package com.synchronous;

import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

////读者可以同时读取数据库,只能有一个可以写数据库,读写操作不能同时进行
/////写者优先
public class WriterAndReader1 {
    int AR=0;   //正在运行的读操作
    int AW=0;   //正在运行的写操作
    int WR=0;   //等待运行的读操作
    int WW=0;   //等待运行的写操作
    final Object okToWirte;
    final Object okToRead;
    final Lock lock;

    public WriterAndReader1() {
        this.lock = new ReentrantLock();
        this.okToWirte = new Object();
        this.okToRead = new Object();

    }
    public void WriteDatabase() throws InterruptedException {
        int time=new Random().nextInt(2000);
        System.out.println("写入数据库操作"+time);
        Thread.sleep(time);
        System.out.println("写入数据库操作完成"+time);
    }
    public void ReadDatabase() throws InterruptedException {
        int time=new Random().nextInt(2000);
        System.out.println("读取数据库操作"+time);
        Thread.sleep(time);
        System.out.println("读取数据库操作完成"+time);
    }
    public void StartRead() throws InterruptedException {
        lock.lock();    //锁住管程区
        while (AW+WW>0){    //如果等待写入和正在写入操作>0,则okToRead等待写操作完成
            WR++;   //等待读操作+1
            lock.unlock();  //释放管程锁
            synchronized (okToRead){
                okToRead.wait();
            }   //等待读操作可以执行
            lock.lock();    //获取管程区锁锁
            WR--;   //等待读操作-1
        }
        AR++;   //开始读操作
        lock.unlock();  //释放管程区锁
    }
    public void DoneRead(){
        lock.lock();
        AR--;   //读操作完成,ARR-1
        if(AR==0 && WW>0){  //如果没有正在运行的读操作及有正在等待的写操作
            synchronized (okToWirte){
            okToWirte.notify();
            } //唤醒写操作
        }
        lock.unlock();
    }
    public void StartWrite() throws InterruptedException {
        lock.lock();    //获取管程区的锁
        while (AW+AR>0){
            WW++;   //等待写操作++
            lock.unlock();  //解锁
            synchronized (okToWirte){
                okToWirte.wait();
            }   //等待写操作可以执行
            lock.lock(); //获取管程区的锁
            WW--;   //等待写操作--
        }
        AW++; //正在写操作+1
        lock.unlock();
    }
    public void DoneWrite(){
        lock.lock();
        AW--;
        if(WW>0){
            synchronized (okToWirte){
                okToWirte.notify();
            }
        }    //如果还有等待的写操作,唤醒写操作

        else if(WR>0){
            synchronized (okToRead){
                okToRead.notifyAll();
            }
        }   //如果有等待的读操作,唤醒所有读操作

        lock.unlock();
    }
    public void Reader() throws InterruptedException {
        StartRead();
        ReadDatabase();
        DoneRead();
    }
    public void Writer() throws InterruptedException {
        StartWrite();
        WriteDatabase();
        DoneWrite();
    }

    public static void main(String[] args) {
        int flag= 0;
        WriterAndReader1 writerAndReader = new WriterAndReader1();
        for(int i=0;i<=20;i++){
            flag=new Random().nextInt(100);
            if (flag%3==0){
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        try {
                            writerAndReader.Writer();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
            else {
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        try {
                            writerAndReader.Reader();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }
    }
}

©AHIEC人工智能工作室 2021

地址:安徽省合肥市包河区梁园路安徽工业经济职业技术学院现代科教中心101室

创作者信息:

皖ICP备20011723号-2