其实我关于代码中信号量和管程的具体差别不是特别的清楚。
但是因为用到了Semaphore类(信号量),就是用信号量实现的。程序员们需要自己对信号量的初始化、更新(wait/signal)以及信号量更新逻辑负责。
而管程应该是用到了synchronized的定义方法,如public synchronized void insert(int val)
,这个时候并不需要自己去实现信号量的等待、释放,只需要直接调用就行,
import java.util.*;
public class ProduceConsume {
static final int N = 2;//define the size of the buffer
static producer p = new producer();//initial a thread of producer
static consumer c = new consumer();//initial a thread of consumer
static our_monitor mon = new our_monitor();//initial a thread of a new pipe
public static void main(String args[])
{
p.start();
c.start();
}
static class producer extends Thread {
public void run()
{
int item;
while(true) //the loop of a producer
{
item = produce_item();
mon.insert(item);
}
}
private int produce_item()
{
int p=1;
System.out.println("Produce:"+p);
return p;
}
}
static class consumer extends Thread {
public void run()
{
int item;
while(true)
{
item = mon.remove();
consume_item(item);
}
}
private void consume_item(int item)
{
System.out.println("consumer:"+item);
}
}
static class our_monitor //a pipe {
private int buffer[] = new int[N];
private int count = 0,lo = 0, hi = 0;
public synchronized void insert(int val)
{
try
{
Thread.sleep(500);
}
catch(InterruptedException e)
{
System.out.println("error");
}
if(count == N)go_to_sleep();
buffer[hi] = val;
hi=(hi + 1) % N;
count = count + 1;
if(count == 1)notify();
}
public synchronized int remove()
{
try
{
Thread.sleep(500);
}
catch(InterruptedException e)
{
System.out.println("error");
}
int val;
if(count == 0)go_to_sleep();
val = buffer[lo];
lo = (lo + 1) % N;
count = count -1;
if(count == N-1)notify();
return val;
}
private void go_to_sleep()
{
try
{
wait();
}
catch(InterruptedException e)
{
System.out.println("error");
}
}
}
}
这是用信号量实现的。
import java.util.*;
import java.util.concurrent.Semaphore;
public class OS_Readerwriter {
static Semaphore sem=new Semaphore(1);
static Semaphore sem_wrt=new Semaphore(1);
static int readercount=0;
static String a="hahaha";
public static void main(String args[])
{
class reader implements Runnable {
public reader()
{
}
@Override
public void run()
{
// TODO Auto-generated method stub
try
{
sem.acquire();
readercount++;
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
if(readercount==1)
{
try
{
sem_wrt.acquire();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
sem.release();
System.out.println("Reading "+a);
try
{
sem.acquire();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
readercount--;
if(readercount==0)
{
sem_wrt.release();
}
sem.release();
}
}
class writer implements Runnable {
public writer()
{
}
@Override
public void run()
{
// TODO Auto-generated method stub
try
{
sem_wrt.acquire();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
a=a+"abc";
System.out.println("Writing "+a);
sem_wrt.release();
}
}
for(int i=1; i<=10; i++)
{
new Thread(new writer()).start();
new Thread(new reader()).start();
}
}
}
下面是用管程方式实现的
Reader 类
public class Reader extends Thread {
private Database server;//设置一个Database变量用来控制该读者
private int readerNum;//设置该读者的标志
public Reader(int r, Database db)
{
readerNum = r;
server = db;
}
@Override
public void run()
{
int c;
while (true)
{
System.out.println("reader " + readerNum + " is sleeping");
Database.napping();//表明读者正在睡眠状态
System.out.println("reader " + readerNum + " wants to read");
c = server.startRead();//读者开始请求读入工作
System.out.println("reader " + readerNum + " is reading. Count=" + c);
Database.napping();//读者处于工作阶段
c = server.endReading();//读者结束工作
System.out.println("It is reader " + readerNum + " who has done reading according to count=" + c);
}
}
}
Writer类
public class Writer extends Thread {
private Database server;//设置一个Database变量用来控制该写者
private int writerNum;//设置该写者的标志
public Writer(int w, Database db)
{
writerNum = w;
server = db;
}
@Override
public void run()
{
while (true)
{
System.out.println("Writer " + writerNum + " is sleeping");
Database.napping();//表明写者正在睡眠状态
System.out.println("Writer " + writerNum + " wants to write");
server.startWriting();//写者开始请求读入工作
System.out.println("Writer " + writerNum + " is writing");
Database.napping();//写者处于工作阶段
server.endWriting();//写者结束工作
System.out.println("It is Writer " + writerNum + " who has done writing .");
}
}
}
Database类(临界资源)
public class Database
{
private static final int NAP_TIME = 5;
private int readerCount;//变量计数需要读的读者
private int writerCount;//变量计数需要写的写者
private boolean dbReading;//表示是否有读者在读
private boolean dbWriting;//表示是否有写者在写
public Database()
{
readerCount = 0;//变量计数需要读的读者为0
writerCount = 0;//变量计数需要写的写者为0
dbReading = false;//表示没有读者正在读入
dbWriting = false;//表示没有写者正在写入
}
public static void napping() //控制睡眠的时间
{
int sleepTime = (int) (NAP_TIME * Math.random());//睡眠时间随机
try
{
Thread.sleep(sleepTime * 1000);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public synchronized int startRead() //控制读者开始读
{
if (dbReading == false) //当没有读者在读时
{
while (writerCount > 0) //当有写者想写时
{
try
{
System.out.println("reader is waiting");
wait();//等待
}
catch (Exception e)
{
System.out.println(e.toString());
e.printStackTrace();
}
}
}
++readerCount;//请求读入的读者数加一
if (readerCount == 1)
{
dbReading = true;//标明有读者正在读
}
return readerCount;
}
public synchronized int endReading() //控制读者结束读入
{
--readerCount;
if (readerCount == 0)
{
dbReading = false;
}
notifyAll();//释放出空间给其他的线程
System.out.println("one reader is done, reading. Count=" + readerCount);
return readerCount;
}
public synchronized void startWriting() //控制写者开始进入写
{
++writerCount;//想写的写者数加一
while (dbReading == true || dbWriting == true) //当有读者在读或者有写者在写时都得等待
{
try
{
System.out.println("Writer is waiting");
wait();
}
catch (Exception e)
{
System.out.println(e.toString());
}
}
dbWriting = true;
}
public synchronized void endWriting() //控制写者结束写入
{
--writerCount;
dbWriting = false;
System.out.println("one writer is done, writing. Count=" + writerCount);
notifyAll();
}
}
Main类
/** * * @author PhoebeWu */
public class Main {
public static void main(String[] args)
{
Database db=new Database();//实例化类Database为db
Reader r1=new Reader(1,db);//实例化类Reader为r1
Reader r2=new Reader(2,db);
Reader r3=new Reader(3,db);
Reader r4=new Reader(4,db);
Writer w1=new Writer(1,db);//实例化类Writer为w1
Writer w2=new Writer(2,db);
r1.start();//读者1调用start()方法开始进入读写这个模拟环境中
r2.start();
r3.start();
w1.start();
r4.start();
w2.start();
}
}
下面这段代码是用信号量实现的。
import java.util.concurrent.Semaphore;
public class OS_Philosopher {
static int chop[]=new int [7];
static Semaphore []sem=new Semaphore[7];
public static void main(String args[]) throws InterruptedException
{
for(int i=0; i<=6; i++)
{
sem[i]=new Semaphore(1);
}
Thread.sleep(1000);
class philosopher implements Runnable{
int i;
public philosopher(int i)
{
this.i=i;
}
@Override
public void run()
{
// TODO Auto-generated method stub
while(true)
{
try
{
synchronized(this)
{
sem[i].acquire();
sem[(i+1)%5].acquire();
}
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Phi"+i+" is Eating");
//sleep();
try
{
Thread.sleep(1);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
sem[i].release();
sem[(i+1)%5].release();
System.out.println("Phi"+i+" is Thinking");
//sleep();
try
{
Thread.sleep(1);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
philosopher t1=new philosopher(1);
philosopher t2=new philosopher(2);
philosopher t3=new philosopher(3);
philosopher t4=new philosopher(4);
philosopher t5=new philosopher(5);
new Thread(t1).start();
new Thread(t2).start();
new Thread(t3).start();
new Thread(t4).start();
new Thread(t5).start();
}
}
下面是管程实现
Chopstick类
/** * 表示筷子的类 * */
public class Chopstick{
public Chopstick(){
}
public Chopstick(int id){
this.id = id;
}
public boolean isAvailable(){
return available;
}
public void setAvailable(boolean available){
this.available = available;
}
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
@Override
public String toString(){
return "筷子" + id;
}
/** * 表示筷子是否可用 * */
private volatile boolean available = true;
private int id;
}
ChopstickArray类
public class ChopstickArray{
public ChopstickArray(){
}
public ChopstickArray(int size){
chopsticks = new Chopstick[size];
for(int i = 0; i < chopsticks.length; ++i){
chopsticks[i] = new Chopstick(i);
}
}
public Chopstick getId(int id){
return chopsticks[id];
}
public Chopstick getLast(int id){
if(id == 0){
return chopsticks[chopsticks.length - 1];
}else{
return chopsticks[id - 1];
}
}
private Chopstick[] chopsticks;
}
Philosopher类
import java.util.Random;
import javax.swing.JTextArea;
public class Philosopher implements Runnable{
public Philosopher(){
}
public Philosopher(int id, ChopstickArray chopstickArray){
this.id = id;
this.chopstickArray = chopstickArray;
}
public synchronized void thinking(){
if(state){ // 如果在思考,说明这个哲学家两面的筷子没用
chopstickArray.getId(id).setAvailable(true);
chopstickArray.getLast(id).setAvailable(true);
System.out.println(this.toString() + "在思考");
try{
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}
state = false;
}
public synchronized void eating(){
if(!state){ // 在思考
if(chopstickArray.getId(id).isAvailable()){ // 如果哲学家右手边的筷子可用
if(chopstickArray.getLast(id).isAvailable()){ // 如果左手边的筷子也可用
// 然后将这个能吃饭的哲学家两侧的筷子都设置为不可用
chopstickArray.getId(id).setAvailable(false);
chopstickArray.getLast(id).setAvailable(false);
System.out.println(this.toString() + "在吃饭");
try{
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}else{
// 右手边的筷子可用,但是左手边的不可用
System.out.println(this.toString() + "在等待"
+ chopstickArray.getLast(id));
try{
wait(new Random().nextInt(100));
}catch(Exception e){
e.printStackTrace();
}
}
}else{
// 如果哲学家右手边的筷子不可用则等待
System.out.println(this.toString() + "在等待"
+ chopstickArray.getId(id));
try{
wait(new Random().nextInt(100));
}catch(Exception e){
e.printStackTrace();
}
}
}
state = true;
}
@Override
public void run(){
for(int i = 0; i < 10; ++i){
thinking();
eating();
}
}
@Override
public String toString(){
return " 哲学家 " + id;
}
private int id;
private boolean state;
ChopstickArray chopstickArray;
}
Main类
public class Main
{
public static void main(String[] args)
{
ChopstickArray chopstickArray = new ChopstickArray(5);
for(int i = 0; i < 5; i++)
{
new Thread(new Philosopher(i, chopstickArray)).start();
}
}
}
//没有仔细检查逻辑,可能...有可能死锁
桌上有一个空盘子,只允许放一个水果。爸爸可以向盘中放苹果,也可以向盘中放桔子,儿子专等吃盘中的桔子,女儿专等吃盘中的苹果。规定当盘空时,一次只能放一只水果。
下面是程序的具体实现代码,在写这个程序的时候,有点小问题,纠结了很长时间,于是在csdn论坛上发表帖子终于得到了解决
先说说涉及到的类的作用,首先Fruits作为一个水果的父类,Apple和Orange是Fruits类的扩展类。CriticalResources类是临界资源类,作为缓冲区用,里面封装了数组大小为一的Fruits数组,可以看成“盘子”;ProducerOrange为生产橘子的类 ProducerApple为生产桔子的类 ConsumerApple(消费苹果的类) ConsumerOrange(消费桔子的类)。
水果类(用于继承)
public class Fruits {
private String name;
public Fruits(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
public Fruits() {
super();
}
}
Apple类
public class Apple extends Fruits {
public Apple(String name) {
super(name);
}
public Apple() {
// TODO Auto-generated constructor stub
}
}
Orange类
public class Orange extends Fruits {
public Orange(String name) {
super(name);
}
public Orange() {
// TODO Auto-generated constructor stub
}
}
ProducerApple类
/** * 生产苹果的生产者 * * @author PhoebeWu * */
public class ProducerApple implements Runnable {
private CriticalResources cr = null;// 封装一个临界资源对象,以便生产
public ProducerApple(CriticalResources cr) {
super();
this.cr = cr;
}
private int count = 5;
@Override
public void run() {
while (count-- > 0)
synchronized (cr) {
while ((cr.peek() != null)) {
try {
cr.wait();// 缓冲区满,该生产者等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果不加锁,此处容易被打断
Fruits fruits = new Apple("苹果");
cr.push(fruits);
System.out.println("苹果生产商生产了" + fruits);
cr.notifyAll();
}
}
}
ProducerOrange类
public class ProducerOrange implements Runnable {
CriticalResources cr = null;
public ProducerOrange(CriticalResources cr) {
super();
this.cr = cr;
}
int count = 5; //做5次
@Override
public void run() {
while(count-->0)
synchronized (cr) {
while (cr.peek() != null) {
try {
cr.wait();// 该生产这等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Fruits fruits = new Orange("橘子");
cr.push(fruits);
System.out.println("橘子生产商生产了" + fruits);
cr.notifyAll();
}
}
}
ConsumerApple类
/** * 消费苹果的消费者 * * @author PhoebeWu * */
public class ConsumerApple implements Runnable {
private CriticalResources cr = null;// 封装一个临界资源对象,以便消费
public ConsumerApple(CriticalResources cr) {
super();
this.cr = cr;
}
int count = 5;
@Override
public void run() {
while(count-->0)
synchronized (cr) {
while (!(cr.peek() instanceof Apple) ) {
try {
cr.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Fruits fruits = cr.pop();
System.out.println("----苹果消费者消费了-------" + fruits);
cr.notifyAll();
}
}
}
ConsumerOrange类
/** * 消费橘子的消费者 * * @author PhoebeWu * */
public class ConsumerOrange implements Runnable {
private CriticalResources cr = null;// 封装一个临界资源对象,以便消费
public ConsumerOrange(CriticalResources cr) {
super();
this.cr = cr;
}
int count = 5;
@Override
public void run() {
while (count-- > 0)
// 如果缓冲区是苹果
synchronized (cr) {
while (!(cr.peek() instanceof Orange)) {
try {
cr.wait();// 该消费者等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Fruits fruits = cr.pop();
System.out.println("----橘子消费者消费了-------" + fruits);
cr.notifyAll();
}
}
}
CriticalResources类
public class CriticalResources {
private int index = 0;
private static Fruits[] fruites = new Fruits[1];// 默认临界区有五个商品
private ProducerApple pa = new ProducerApple(this);
private ProducerOrange po = new ProducerOrange(this);
private ConsumerApple ca = new ConsumerApple(this);
private ConsumerOrange co = new ConsumerOrange(this);
/** * 向临界资源里添加商品 利用synchronized关键字实现同步 添加后数组指针+1 * 如果临界资源数组里面装满了商品不能再生产,则生产线程等待以便让消费者消费 * * @param goods */
public synchronized void push(Fruits goods) {
//
while (this.index == this.fruites.length) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.notifyAll();// 唤醒生产者
this.fruites[index++] = goods;
}
/** * 从临界资源里拿商品,先减一后返回 如果index==0说明, 临界资源数组里面没有商品,不能在消费 消费线程阻塞, 让生产者生产 则让生产者 * * @return */
public synchronized Fruits pop() {
while (this.index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.notifyAll();// 唤醒消费者
return fruites[--index];
}
/** * 是否为空 * * @return */
public synchronized Fruits peek() {
if (this.index == 0)
return null;
else
return fruites[index - 1];
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public Fruits[] getFruites() {
return fruites;
}
}
Client类
public class Client {
public static void main(String[] args) {
CriticalResources cr = new CriticalResources();
// 生产苹果实例
ProducerApple appleP = new ProducerApple(cr);
// 消费苹果实例
ConsumerApple appleC = new ConsumerApple(cr);
// 橘子生产者实例
ProducerOrange orangeP = new ProducerOrange(cr);
// 橘子消费者实例
ConsumerOrange orangeC = new ConsumerOrange(cr);
// 生产苹果线程
Thread pThread = new Thread(appleP);
// 消费苹果线程
Thread cThread = new Thread(appleC);
// 生产橘子线程
Thread pt = new Thread(orangeP);
// 消费橘子线程
Thread ct = new Thread(orangeC);
pThread.start();
cThread.start();
pt.start();
ct.start();
}
}
我并不是很懂这个问题具体是怎么回事儿。
这里假设水是临界资源,两个和尚是线程。每次只有一个和尚去挑水。
monk类
import java.util.*;
public class monk extends Thread {
private String name;
private water w = new water();
private Random r = new Random();
monk(){
}
monk(String _name){
this.name = _name;
}
public void run()
{
while(true){
w.carry(name, r.nextInt(3));
}
}
}
water类
public class water {
public synchronized void carry(String name, long time)
{
try{
Thread.sleep(time * 1000);
}catch(InterruptedException e){
System.out.println("Error");
}
System.out.println(name + "正在挑水");
}
}
Main类
public class Main {
static monk littleMonk = new monk(new String("LittleMonk"));
static monk oldMonk = new monk(new String("OldMonk"));
static public void main(String args[])
{
littleMonk.start();
oldMonk.start();
}
}