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