操作系统概念 管程Java代码实现

java中利用管程实现同步互斥量

其实我关于代码中信号量和管程的具体差别不是特别的清楚。
但是因为用到了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();
    }
}

你可能感兴趣的:(java,操作系统,信号量,管程)