经典同步互斥问题之读者—写者问题

问题描述:


第一次看到这个问题的时候,感觉很简单,不屑于看,然而当我上手敲代码的时候就懵逼了:道理很清楚很明白,可是代码实现确不是那么简单,想了一天都没想通。第二天参考了一篇文章,才理清思路。贴上我认为最简短的而且还能达到题目要求解决所给问题的代码:

//Test.java
import java.io.BufferedReader;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

public class Test {

	/**
	 * @param args
	 * 创建了五个线程(四个读,一个写),让它们自己竞争,所以每次运行代码结果是不一样滴。
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Ticket ticket=new Ticket(100);
		Mythread mythread1=new Mythread(ticket,"R");
		Mythread mythread2=new Mythread(ticket,"R");
		Mythread mythread3=new Mythread(ticket,"W");
		Mythread mythread4=new Mythread(ticket,"R");
		Mythread mythread5=new Mythread(ticket,"R");			
		mythread1.start();
		mythread3.start();	
		mythread2.start();
		mythread4.start();
		mythread5.start();
	}
}
//Ticket.java
public class Ticket {
	private int num;
	//标记当前是否有写线程正在执行
	private Boolean write=false;
	Ticket(){}
	Ticket(int n){
		this.num=n;
	}
	public int read(){
		System.out.println("====================================");
		System.out.println("我是读,我来了");
		while(true){
			if(this.write){
				//如果有写线程正在执行
				System.out.println("wait...");
				try{wait();}catch (Exception e) {}
			}			
			else{
				System.out.println("剩余票数:"+this.num);
				break;
			}
		}	
		System.out.println("我读完了");
		System.out.println("====================================");
		return this.num;
		
	}
	public synchronized void write(){
		this.write=true;//进入写线程,首先改变标记
		System.out.println("====================================");
		System.out.println("我是写,我来了");
		
		this.num--;	
//		try {
//			Thread.sleep(10);
//		} catch (InterruptedException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}  	
		System.out.println("修改后的票数:"+this.num);
		System.out.println("我写完了");	
		System.out.println("====================================");
		this.write=false;//退出写线程,恢复标记
	} 
}
//Mythread.java
public class Mythread extends Thread{
	Ticket ticket;
	public String flag;//标记该线程是读或写
	Mythread(Ticket tic,String ch){
		this.ticket=tic;
		this.flag=ch;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		if("W".equals(this.flag)){
			this.ticket.write();
		}
		else if("R".equals(this.flag)){
			this.ticket.read();			
		}
	}
}

核心代码在Ticket.java类,也不多,哈哈。。


可以看到:当有写操作的时候,无论当前的读操作是否完成,都得进入阻塞,等待写操作完成后,再进行读操作。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值