转---秒杀多线程第十二篇 多线程同步内功心法——PV操作上 (续)

PV操作的核心就是 PV操作可以同时起到同步与互斥的作用。

1.同步就是通过P操作获取信号量,V操作释放信号量来进行。

2.互斥其实就是,同时操作P操作,结束后进行V操作即可做到。

 

Java上实现PV操作可以通过Semaphore来实现。

package com.multithread.pvoperator;



import java.util.concurrent.Semaphore;



/*

    P(S):

    

    ①将信号量S的值减1,即S=S-1;

    

    ②如果S>=0,则该进程继续执行;否则该进程置为等待状态。

    

    V(S):

    

    ①将信号量S的值加1,即S=S+1;

    

    ②该进程继续执行;如果该信号的等待队列中有等待进程就唤醒一等待进程。

 * 

 * */

public class PVObject {

    

    private Semaphore mSemaphore =null;

    private int Max_size = 0xff;

    private String name = null;

    public PVObject(int size,String name)

    {

        if(size>0)

        {

            Max_size = size;

            mSemaphore = new Semaphore(size);

        }

        this.name = name;

    }

    

    public PVObject(String name)

    {

        Max_size = 1;

        mSemaphore = new Semaphore(1);

        this.name = name;

    }

    

    public void Init(int status)

    {

        if(status<0 || status>Max_size)

        {

            System.out.println("[PVObject][Init]"+name+" wrong,status:"+status);

            return;

        }

        

        if(status == Max_size)

        {

            return;

        }

        

        try {

            mSemaphore.release(Max_size);

            mSemaphore.acquire(Max_size-status);

        } catch (InterruptedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }    

    }

    

    public void P()

    {

        try {

            //

            mSemaphore.acquire();

        } catch (InterruptedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }        

    }

    

    public void V()

    {

        mSemaphore.release();        

    }

}

分水果问题Java是实现:

package com.multithread.pvoperator;



import java.util.LinkedList;

import java.util.Queue;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.Executor;

import java.util.concurrent.Executors;



public class Fruit {

    /*

     * 下面先考虑同步情况即所有“等待”情况:

        第一.爸爸要等待盘子为空。

        第二.儿子要等待盘中水果是桔子。

        第三.女儿要等待盘中水果是苹果。

        接下来来考虑要互斥处理的资源,看起来盘子好像是要作互斥处理的,

        但由于题目中的爸爸、儿子、女儿均只有一个,并且他们访问盘子的条件都不一样,

        所以他们根本不会同时去访问盘子,因此盘子也就不用作互斥处理了

     * 

     * */

    public PVObject mEmptyDash = new PVObject("emptyDash");//1

    public PVObject mApple = new PVObject("apple");    //0

    public PVObject mOranger = new PVObject("oranger");  //0

    public boolean mDadEnd = false;

    public CountDownLatch mLatchDown = new CountDownLatch(3);

    public CountDownLatch mLatchStart = new CountDownLatch(3);

    public Queue<Integer> mQueue = new LinkedList<Integer>();

    public void Start()

    {

        mEmptyDash.Init(1);

        mApple.Init(0);

        mOranger.Init(0);

        mQueue.clear();

        Executor mEcecutor = Executors.newFixedThreadPool(5);

        mEcecutor.execute(new Dad(this));

        mEcecutor.execute(new Daughter(this));

        mEcecutor.execute(new Son(this));



        try {

            mLatchStart.await();

            System.out.println("all thread start");

            

            mLatchDown.await();

            System.out.println("all thread down");

        } catch (InterruptedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

    

    

    public class Dad extends Thread{

        

        public Fruit mFruit = null;

        boolean flag = true;

        public int MAX_FRUIT_COUNT = 20;

        public int index = 0;

        public Dad(Fruit f)

        {

            mFruit = f;

        }

        @Override

        public void run() {

            mLatchStart.countDown();

            while(flag)

            {

                mFruit.mEmptyDash.P();

                

                index++;

                if(index >=MAX_FRUIT_COUNT)

                {

                    flag = false;

                }

                

                mQueue.offer(index);

                

                if((int)(Math.random()*2) == 1)

                {

                    System.out.println("dad put apple"+index+" to dash");

                    //apply

                    mFruit.mApple.V();

                }

                else

                {

                    //oranger

                    System.out.println("dad put oranger"+index+" to dash");

                    mFruit.mOranger.V();

                }

            }

            mFruit.mDadEnd = true;

            System.out.println("dad thread is end");

            mLatchDown.countDown();

        }

    }

    

    public class Daughter extends Thread{

        

        public Fruit mFruit = null;

        boolean flag = true;

        public Daughter(Fruit f)

        {

            mFruit = f;

        }

        @Override

        public void run() {

            mLatchStart.countDown();

            while(flag)

            {

                mFruit.mOranger.P();

                if(mQueue.size()>0)

                {

                    System.out.println("Daughter get oranger"+mQueue.poll()+" from dash");                

                    mFruit.mEmptyDash.V();

                }

                else

                {

                    System.out.println("Daughter get oranger from dash,but dash is empty");                

                }

                

                if(mFruit.mDadEnd == true)

                {

                    flag = false;

                }

            }

            System.out.println("Daughter thread is end");

            //notify son down,for this dad is down.

            mApple.V();

            mLatchDown.countDown();

        }

    }

    

    public class Son extends Thread{

        

        public Fruit mFruit = null;

        boolean flag = true;

        public Son(Fruit f)

        {

            mFruit = f;

        }

        @Override

        public void run() {

            mLatchStart.countDown();

            while(flag)

            {

                mFruit.mApple.P();

                if(mQueue.size()>0)

                {

                    System.out.println("Son get apple"+mQueue.poll()+" from dash");                

                    mFruit.mEmptyDash.V();

                }

                else

                {

                    System.out.println("Son get apple from dash,but dash is empty");                

                }

                

                if(mFruit.mDadEnd == true)

                {

                    flag = false;

                }

            }

            System.out.println("Son thread is end");

            mOranger.V();

            mLatchDown.countDown();

        }

    }

}

安全岛问题:

package com.multithread.pvoperator;



import java.util.concurrent.CountDownLatch;

import java.util.concurrent.Executor;

import java.util.concurrent.Executors;



public class SafeIsland {

    

    public PVObject NT = new PVObject("NLoad");

    public PVObject TN = new PVObject("TLoad");

    public PVObject K = new PVObject("K");

    public PVObject L = new PVObject("L");

    public static final int MAX_NANKAI_CAR_COUNT = 2;

    public static final int MAX_TIANJING_CAR_COUNT = 3;

    public CountDownLatch mLatchDown = new CountDownLatch(MAX_NANKAI_CAR_COUNT+MAX_TIANJING_CAR_COUNT);

    

    public class NanKaiCar extends Thread{

        String name = null;

        public NanKaiCar(String name)

        {

            this.name = name;

        }

        @Override

        public void run() {

            System.out.println("[NanKaiCar]"+name+" Thread start");

            try {

                Thread.sleep((long) (Math.random()*100));

                NT.P();

                System.out.println("[NanKaiCar]"+name+" enter crossing N");

                K.P();

                System.out.println("[NanKaiCar]"+name+" walk to M:N->M");

                Thread.sleep((long) (Math.random()*1000));

                System.out.println("[NanKaiCar]"+name+" start walk to T");

                K.V();

                L.P();

                System.out.println("[NanKaiCar]"+name+" walk to T:M->T");

                L.V();

                NT.V();

            } catch (InterruptedException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

            mLatchDown.countDown();

            System.out.println("[NanKaiCar]"+name+" walk down");

        }

        

        

    }

    

    public class TianJingCar extends Thread{

        String name = null;

        public TianJingCar(String name)

        {

            this.name = name;

        }

        @Override

        public void run() {

            

            try {

                System.out.println("[TianJingCar]"+name+" Thread start");

                Thread.sleep((long) (Math.random()*100));

                TN.P();

                System.out.println("[TianJingCar]"+name+" enter crossing T");

                L.P();

                System.out.println("[TianJingCar]"+name+" walk to M:T->M");

                Thread.sleep((long) (Math.random()*1000));

                System.out.println("[TianJingCar]"+name+" start walk to N");

                L.V();

                K.P();

                System.out.println("[TianJingCar]"+name+" walk to T:M->N");

                K.V();

                TN.V();

            } catch (InterruptedException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

            mLatchDown.countDown();

            System.out.println("[TianJingCar]"+name+" walk down");

        }        

        

    }



    public void start()

    {

        NT.Init(1);

        TN.Init(1);

        K.Init(1);

        L.Init(1);

        Executor mEcecutor = Executors.newFixedThreadPool(MAX_TIANJING_CAR_COUNT+MAX_NANKAI_CAR_COUNT+1);

        for(int i =1;i<=MAX_NANKAI_CAR_COUNT;i++)

        {

            mEcecutor.execute(new NanKaiCar("carN"+i));

        }

        for(int j=1;j<=MAX_TIANJING_CAR_COUNT;j++)

        {

            mEcecutor.execute(new TianJingCar("carT"+j));

        }

        try {

            mLatchDown.await();

            System.out.println("all car has pass road");

        } catch (InterruptedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }



}

生产消费者问题伪代码:

package com.multithread.pvoperator;



public class Prosumer {

    //PV 分析 生产者,消费者问题

    /*同步:    生产者:缓冲区有空间,就放入数据  P(EmptyS) 只有空和不空,信号量为1

     *        消费者:缓冲区有数据,就读取数据,并移走数据 P(NotEmptyS),信号量为缓冲区大小

     *互斥:    生产者 写入数据,和消费者移走数据互斥 P(OperatorS),用来互斥,信号量为1

     *        消费者异步读取移动数据,互斥          

     * */

    public class Productor extends Thread{



        @Override

        public void run() {

            while(true)

            {

                P(EmptyS);

                P(OperatorS);

                //operator data

                V(OperatorS);

                V(NotEmptyS);//通知不为空

            }

        }

        

        

    }

    

    public class Consumer extends Thread{



        @Override

        public void run() {

            P(NotEmptyS);

            P(OperatorS);

            //operator data

            V(OperatorS);

            V((EmptyS);

        }        

    }

}

 

 

 

package com.multithread.pvoperator;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class Fruit {
    /*
     * 下面先考虑同步情况即所有“等待”情况:
        第一.爸爸要等待盘子为空。
        第二.儿子要等待盘中水果是桔子。
        第三.女儿要等待盘中水果是苹果。
        接下来来考虑要互斥处理的资源,看起来盘子好像是要作互斥处理的,
        但由于题目中的爸爸、儿子、女儿均只有一个,并且他们访问盘子的条件都不一样,
        所以他们根本不会同时去访问盘子,因此盘子也就不用作互斥处理了
     *
     * */
    public PVObject mEmptyDash = new PVObject("emptyDash");//1
    public PVObject mApple = new PVObject("apple");    //0
    public PVObject mOranger = new PVObject("oranger");  //0
    public boolean mDadEnd = false;
    public CountDownLatch mLatchDown = new CountDownLatch(3);
    public CountDownLatch mLatchStart = new CountDownLatch(3);
    public Queue<Integer> mQueue = new LinkedList<Integer>();
    public void Start()
    {
        mEmptyDash.Init(1);
        mApple.Init(0);
        mOranger.Init(0);
        mQueue.clear();
        Executor mEcecutor = Executors.newFixedThreadPool(5);
        mEcecutor.execute(new Dad(this));
        mEcecutor.execute(new Daughter(this));
        mEcecutor.execute(new Son(this));

        try {
            mLatchStart.await();
            System.out.println("all thread start");
            
            mLatchDown.await();
            System.out.println("all thread down");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    
    public class Dad extends Thread{
        
        public Fruit mFruit = null;
        boolean flag = true;
        public int MAX_FRUIT_COUNT = 20;
        public int index = 0;
        public Dad(Fruit f)
        {
            mFruit = f;
        }
        @Override
        public void run() {
            mLatchStart.countDown();
            while(flag)
            {
                mFruit.mEmptyDash.P();
                
                index++;
                if(index >=MAX_FRUIT_COUNT)
                {
                    flag = false;
                }
                
                mQueue.offer(index);
                
                if((int)(Math.random()*2) == 1)
                {
                    System.out.println("dad put apple"+index+" to dash");
                    //apply
                    mFruit.mApple.V();
                }
                else
                {
                    //oranger
                    System.out.println("dad put oranger"+index+" to dash");
                    mFruit.mOranger.V();
                }
            }
            mFruit.mDadEnd = true;
            System.out.println("dad thread is end");
            mLatchDown.countDown();
        }
    }
    
    public class Daughter extends Thread{
        
        public Fruit mFruit = null;
        boolean flag = true;
        public Daughter(Fruit f)
        {
            mFruit = f;
        }
        @Override
        public void run() {
            mLatchStart.countDown();
            while(flag)
            {
                mFruit.mOranger.P();
                if(mQueue.size()>0)
                {
                    System.out.println("Daughter get oranger"+mQueue.poll()+" from dash");                
                    mFruit.mEmptyDash.V();
                }
                else
                {
                    System.out.println("Daughter get oranger from dash,but dash is empty");                
                }
                
                if(mFruit.mDadEnd == true)
                {
                    flag = false;
                }
            }
            System.out.println("Daughter thread is end");
            //notify son down,for this dad is down.
            mApple.V();
            mLatchDown.countDown();
        }
    }
    
    public class Son extends Thread{
        
        public Fruit mFruit = null;
        boolean flag = true;
        public Son(Fruit f)
        {
            mFruit = f;
        }
        @Override
        public void run() {
            mLatchStart.countDown();
            while(flag)
            {
                mFruit.mApple.P();
                if(mQueue.size()>0)
                {
                    System.out.println("Son get apple"+mQueue.poll()+" from dash");                
                    mFruit.mEmptyDash.V();
                }
                else
                {
                    System.out.println("Son get apple from dash,but dash is empty");                
                }
                
                if(mFruit.mDadEnd == true)
                {
                    flag = false;
                }
            }
            System.out.println("Son thread is end");
            mOranger.V();
            mLatchDown.countDown();
        }
    }
}

你可能感兴趣的:(线程同步)