进程同步程序设计--吃水果

实验内容

桌子上有一只水果篮,最多可容纳两个水果,每次只能放入或者取出一个水果。爸爸专门向水果篮中放香蕉,妈妈专门向水果篮中放草莓,儿子专门等待吃水果篮中的香蕉,女儿专门等吃水果篮中的草莓。每个小孩最多连吃2个水果后,等另一个小孩吃至少一个水果才会再次开始吃水果,为此,水果篮中若连续房4个相同水果,则必须由放置该水果的人将水果拿回1个。试编程实现爸爸、妈妈、儿子、女儿四个人之间的同步。
(1)水果、水果篮均通过导入图片来实现可视化;
(2)放水果、拿水果均有动画显示,包括把水果拿到手上去放、放完空手回来等均通过的动画予以展示;
(3)执行顺序由并发控制机制决定,而非通过延时实现;
(4)要求界面美观、动作流畅。

实验代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace family
{
    public partial class Form1 : Form
    {

        //设置信号量
        public static Mutex mutex=new Mutex();//对水果篮的互斥访问

        public static Semaphore banana = new Semaphore(0,2);//放、吃操作之间的同步信号量
        public static Semaphore strawberry = new Semaphore(0, 2);
        public static Semaphore empty = new Semaphore(2, 2);

        public static Semaphore fatherput = new Semaphore(4, 4);//连放、连吃操作的同步信号量,表示可以连放多少次
        public static Semaphore motherput = new Semaphore(4, 4);
        public static Semaphore soneat = new Semaphore(2, 2);
        public static Semaphore daughtereat = new Semaphore(2, 2);

        public static int put = 0;//记录上一次放水果的人是谁
        public static int eat = 0;

        public static int banana_n = 0;//水果数记录
        public static int strawberry_n = 0;
        public static int empty_n = 2;

        public static int fatherput_n = 0;//记录连放、连吃的次数
        public static int motherput_n = 0;
        public static int soneat_n = 0;
        public static int daughtereat_n = 0;

        public void Painting_ready()//动画前的准备工作
        {
            thefather.Parent = pictureBox1;//背景透明,图片之间尽量无遮挡
            themother.Parent = pictureBox1;
            theson.Parent = pictureBox1;
            thedaughter.Parent = pictureBox1;
            thebanana1.Parent = pictureBox1;
            thebanana2.Parent = pictureBox1;
            thebanana3.Parent = pictureBox1;
            thebanana4.Parent = pictureBox1;
            thestrawberry1.Parent = pictureBox1;
            thestrawberry2.Parent = pictureBox1;
            thestrawberry3.Parent = pictureBox1;
            thestrawberry4.Parent = pictureBox1;
            pictureBox2.Parent = pictureBox1;
            pictureBox3.Parent = pictureBox1;
            textBox1.Parent = pictureBox1;
            textBox2.Parent = pictureBox1;
            thebanana2.Visible = false;//初始化,不可见
            thebanana3.Visible = false;
            thebanana4.Visible = false;
            thestrawberry2.Visible = false;
            thestrawberry3.Visible = false;
            thestrawberry4.Visible = false;
            pictureBox2.Visible = false;
            pictureBox3.Visible = false;
            textBox1.Visible = false;
            textBox2.Visible = false;
        }

        public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void Form1_Load_1(object sender, EventArgs e)
        {
            Painting_ready();
            for (int i = 0; i < 100; i++)
            {
                Thread father = new Thread(Father);//各进程并发
                Thread mother = new Thread(Mother);
                Thread son = new Thread(Son);
                Thread daughter = new Thread(Daughter);
                father.Start();
                mother.Start();
                son.Start();
                daughter.Start();
            }
        }

        public void Father()
        {
            mutex.WaitOne();
            //水果篮已满
            if (empty_n == 0)
            {
                mutex.ReleaseMutex();
                System.Threading.Thread.Sleep(500);
            }
            //水果篮未满
            else
            {
                empty.WaitOne();//申请一个水果篮中的空位
                fatherput.WaitOne();//申请一个爸爸放水果的权限

                Father_move();//对临界资源的访问
                fatherput_n++;

                //如果上一次是妈妈放的水果,就将妈妈的放水果记录全部释放
                if (put == 2)
                {
                    for (int i = 0; i < motherput_n; i++)
                    {
                        motherput.Release();//释放掉所有妈妈申请的放水果的权限,放水果记录重置
                    }
                    motherput_n = 0;
                }

                put = 1;

                if (fatherput_n != 4)
                {
                    banana_n++;
                    empty_n--;
                    mutex.ReleaseMutex();
                    banana.Release();//香蕉资源加一
                    Father_say();
                }
                else//第四次放后,需要再取回一个水果(第四次放置失败)
                {
                    Father_take();
                    fatherput.Release();//退回去一个
                    empty.Release();
                    fatherput_n--;
                    mutex.ReleaseMutex();
                }

            }
        }

        public void Mother()
        {
            mutex.WaitOne();
            //水果篮已满
            if (empty_n == 0)
            {
                mutex.ReleaseMutex();
                System.Threading.Thread.Sleep(500);
            }
            //水果篮未满
            else
            {
                empty.WaitOne();//申请一个水果篮中的空位
                motherput.WaitOne();//申请一个妈妈放水果的权限

                Mother_move();//对临界资源的访问
                motherput_n++;

                //如果上一次是爸爸放的水果,就将爸爸的放水果记录全部释放
                if (put == 1)
                {
                    for (int i = 0; i < fatherput_n; i++)
                    {
                        fatherput.Release();//释放掉所有妈妈申请的放水果的权限,放水果记录重置
                    }
                    fatherput_n = 0;
                }

                put = 2;

                if (motherput_n != 4)
                {
                    strawberry_n++;
                    empty_n--;
                    mutex.ReleaseMutex();
                    strawberry.Release();//草莓资源加一
                    Mother_say();
                }
                else//第四次放后,需要再取回一个水果(第四次放置失败)
                {
                    Mother_take();
                    motherput.Release();//退回去一个
                    empty.Release();
                    motherput_n--;
                    mutex.ReleaseMutex();
                }

            }    
        }

        public void Son()
        {
            mutex.WaitOne();
            //篮中无香蕉
            if (banana_n == 0)
            {
                mutex.ReleaseMutex();
                System.Threading.Thread.Sleep(500);
            }
            //篮中有香蕉
            else
            {
                //已经连吃两次了
                if (soneat_n == 2)
                {
                    mutex.ReleaseMutex();
                    System.Threading.Thread.Sleep(500);
                }
                //还未连吃两次
                else
                {
                    banana.WaitOne();//申请一个香蕉
                    soneat.WaitOne();//申请一个儿子连吃水果的权限

                    Son_move();//对临界资源的访问
                    banana_n--;
                    empty_n++;
                    soneat_n++;

                    //如果上一次是女儿吃的水果,就将女儿的吃水果记录清空
                    if (eat == 2)
                    {
                        for (int i = 0; i < daughtereat_n; i++)
                        {
                            daughtereat.Release();//释放所有女儿申请的连吃水果的权限,连吃记录重置
                        }
                        daughtereat_n = 0;
                    }

                    eat = 1;

                    mutex.ReleaseMutex();
                    empty.Release();//水果篮空位资源加一

                    Son_eat();
                }              
            }
        }

        public void Daughter()
        {
            mutex.WaitOne();
            //篮中无草莓
            if (strawberry_n == 0)
            {
                mutex.ReleaseMutex();
                System.Threading.Thread.Sleep(500);
            }
            //篮中有草莓
            else
            {
                //已经连吃两次了
                if (daughtereat_n == 2)
                {
                    mutex.ReleaseMutex();
                    System.Threading.Thread.Sleep(500);
                }
                //还未连吃两次
                else
                {
                    strawberry.WaitOne();//申请一个草莓
                    daughtereat.WaitOne();//申请一个女儿连吃水果的权限

                    Daughter_move();//对临界资源的访问
                    strawberry_n--;
                    empty_n++;
                    daughtereat_n++;

                    //如果上一次是儿子吃的水果,就将儿子的吃水果记录清空
                    if (eat == 1)
                    {
                        for (int i = 0; i < soneat_n; i++)
                        {
                            soneat.Release();//释放儿子所有申请的连吃水果权限,连吃记录重置
                        }
                        soneat_n = 0;
                    }

                    eat = 2;

                    mutex.ReleaseMutex();
                    empty.Release();//水果篮空位资源加一

                    Daughter_eat();
                }
            }
        }

        public void Father_move()//爸爸放香蕉
        {
            int x, y, bx, by;
            int move_x, move_y;//步长
            int n = 10;
            if (thebanana2.Visible == false && thestrawberry2.Visible == false)//篮子左边无水果
            {
                move_x = 6;
                move_y = 9;
                for(int i = 0; i < n; i++)//爸爸移步到篮子边,放香蕉
                {
                    x = thefather.Location.X + move_x;
                    y = thefather.Location.Y + move_y;
                    bx = thebanana1.Location.X + move_x;
                    by = thebanana1.Location.Y + move_y;
                    thefather.Location = new Point(x, y);
                    thebanana1.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
                thebanana2.Location = new Point(thebanana1.Location.X, thebanana1.Location.Y);//在篮子左边放置了一个香蕉
                thebanana2.Visible = true;
                thebanana1.Visible = false;
                for (int i = 0; i < n; i++)//原路返回
                {
                    x = thefather.Location.X - move_x;
                    y = thefather.Location.Y - move_y;
                    bx = thebanana1.Location.X - move_x;
                    by = thebanana1.Location.Y - move_y;
                    thefather.Location = new Point(x, y);
                    thebanana1.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
                thebanana1.Visible = true;
            }
            else if (thebanana3.Visible == false && thestrawberry3.Visible == false)//篮子右边无水果
            {
                move_x = 12;
                move_y = 9;
                for (int i = 0; i < n; i++)//移步到篮子旁边,放香蕉
                {
                    x = thefather.Location.X + move_x;
                    y = thefather.Location.Y + move_y;
                    bx = thebanana1.Location.X + move_x;
                    by = thebanana1.Location.Y + move_y;
                    thefather.Location = new Point(x, y);
                    thebanana1.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
                thebanana3.Location = new Point(thebanana1.Location.X, thebanana1.Location.Y);//在篮子右边放置了一个香蕉
                thebanana3.Visible = true;
                thebanana1.Visible = false;
                for (int i = 0; i < n; i++)//原路返回
                {
                    x = thefather.Location.X - move_x;
                    y = thefather.Location.Y - move_y;
                    bx = thebanana1.Location.X - move_x;
                    by = thebanana1.Location.Y - move_y;
                    thefather.Location = new Point(x, y);
                    thebanana1.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
                thebanana1.Visible = true;
            }
            //Thread.Sleep(1000);
        }

        public void Father_take()//爸爸取回香蕉
        {
            thebanana1.Visible = false;
            int x, y, bx, by;
            int move_x=6, move_y=9;
            int n = 10;
            for (int i = 0; i < n; i++)
            {
                x = thefather.Location.X + move_x;
                y = thefather.Location.Y + move_y;
                bx = thebanana1.Location.X + move_x;
                by = thebanana1.Location.Y + move_y;
                thefather.Location = new Point(x, y);
                thebanana1.Location = new Point(bx, by);
                Thread.Sleep(100);
            }
            thebanana2.Location = new Point(thebanana1.Location.X, thebanana1.Location.Y);//把篮子左边的香蕉拿走了
            thebanana1.Visible = true;
            thebanana2.Visible = false;
            for (int i = 0; i < n; i++)//拿着香蕉原路返回
            {
                x = thefather.Location.X - move_x;
                y = thefather.Location.Y - move_y;
                bx = thebanana1.Location.X - move_x;
                by = thebanana1.Location.Y - move_y;
                thefather.Location = new Point(x, y);
                thebanana1.Location = new Point(bx, by);
                Thread.Sleep(100);
            }
        }

        public void Father_say()//通知儿子来吃香蕉
        {
            textBox1.Visible = true;
            Thread.Sleep(1000);
            textBox1.Visible = false;
        }

        public void Mother_move()//妈妈放草莓
        {
            int x, y, bx, by;
            int move_x, move_y;//步长
            int n = 10;
            if (thebanana2.Visible == false && thestrawberry2.Visible == false)//盘子左边无水果
            {
                move_x = -10;
                move_y = 9;
                for (int i = 0; i < n; i++)//移步到盘子旁边,放草莓
                {
                    x = themother.Location.X + move_x;
                    y = themother.Location.Y + move_y;
                    bx = thestrawberry1.Location.X + move_x;
                    by = thestrawberry1.Location.Y + move_y;
                    themother.Location = new Point(x, y);
                    thestrawberry1.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
                thestrawberry2.Location = new Point(thestrawberry1.Location.X, thestrawberry1.Location.Y);//在篮子左边放置了一个香蕉
                thestrawberry2.Visible = true;
                thestrawberry1.Visible = false;
                for (int i = 0; i < n; i++)//原路返回
                {
                    x = themother.Location.X - move_x;
                    y = themother.Location.Y - move_y;
                    bx = thestrawberry1.Location.X - move_x;
                    by = thestrawberry1.Location.Y - move_y;
                    themother.Location = new Point(x, y);
                    thestrawberry1.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
                thestrawberry1.Visible = true;
            }
            else if (thebanana3.Visible == false && thestrawberry3.Visible == false)//篮子右边无水果
            {
                move_x = -4;
                move_y = 9;
                for (int i = 0; i < n; i++)//移步到篮子旁边,放草莓
                {
                    x = themother.Location.X + move_x;
                    y = themother.Location.Y + move_y;
                    bx = thestrawberry1.Location.X + move_x;
                    by = thestrawberry1.Location.Y + move_y;
                    themother.Location = new Point(x, y);
                    thestrawberry1.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
                thestrawberry3.Location = new Point(thestrawberry1.Location.X, thestrawberry1.Location.Y);//在篮子右边放置了一个草莓
                thestrawberry3.Visible = true;
                thestrawberry1.Visible = false;
                for (int i = 0; i < n; i++)//妈妈原路返回
                {
                    x = themother.Location.X - move_x;
                    y = themother.Location.Y - move_y;
                    bx = thestrawberry1.Location.X - move_x;
                    by = thestrawberry1.Location.Y - move_y;
                    themother.Location = new Point(x, y);
                    thestrawberry1.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
                thestrawberry1.Visible = true;
            }
            //Thread.Sleep(1000);
        }

        public void Mother_take()//妈妈取回草莓
        {
            thestrawberry1.Visible = false;
            int x, y, bx, by;
            int move_x = -4, move_y = 9;
            int n = 10;
            for (int i = 0; i < n; i++)
            {
                x = themother.Location.X + move_x;
                y = themother.Location.Y + move_y;
                bx = thestrawberry1.Location.X + move_x;
                by = thestrawberry1.Location.Y + move_y;
                themother.Location = new Point(x, y);
                thestrawberry1.Location = new Point(bx, by);
                Thread.Sleep(100);
            }
            thestrawberry3.Location = new Point(thestrawberry1.Location.X, thestrawberry1.Location.Y);//把篮子右边的草莓拿走了
            thestrawberry1.Visible = true;
            thestrawberry3.Visible = false;
            for (int i = 0; i < n; i++)//拿着草莓原路返回
            {
                x = themother.Location.X - move_x;
                y = themother.Location.Y - move_y;
                bx = thestrawberry1.Location.X - move_x;
                by = thestrawberry1.Location.Y - move_y;
                themother.Location = new Point(x, y);
                thestrawberry1.Location = new Point(bx, by);
                Thread.Sleep(100);
            }
        }

        public void Mother_say()//通知女儿来吃草莓
        {
            textBox2.Visible = true;
            Thread.Sleep(1000);
            textBox2.Visible = false;
        }

        public void Son_move()//儿子取香蕉
        {
            int x, y, bx, by;
            int move_x, move_y;//步长
            int n = 10;
            pictureBox2.Visible = false;
            thebanana4.Visible = false;
            if (thebanana2.Visible == true)//篮子左边有香蕉
            {
                move_x = 6;
                move_y = -9;
                for (int i = 0; i < n; i++)
                {
                    x = theson.Location.X + move_x;
                    y = theson.Location.Y + move_y;
                    bx = thebanana4.Location.X + move_x;
                    by = thebanana4.Location.Y + move_y;
                    theson.Location = new Point(x, y);
                    thebanana4.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
                thebanana2.Location = new Point(thebanana4.Location.X, thebanana4.Location.Y);//把篮子左边的香蕉拿走了
                thebanana4.Visible = true;
                thebanana2.Visible = false;
                for (int i = 0; i < n; i++)//拿着香蕉原路返回
                {
                    x = theson.Location.X - move_x;
                    y = theson.Location.Y - move_y;
                    bx = thebanana4.Location.X - move_x;
                    by = thebanana4.Location.Y - move_y;
                    theson.Location = new Point(x, y);
                    thebanana4.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
            }
            else if (thebanana3.Visible == true)//篮子右边有香蕉
            {
                move_x = 12;
                move_y = -9;
                for (int i = 0; i < n; i++)
                {
                    x = theson.Location.X + move_x;
                    y = theson.Location.Y + move_y;
                    bx = thebanana4.Location.X + move_x;
                    by = thebanana4.Location.Y + move_y;
                    theson.Location = new Point(x, y);
                    thebanana4.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
                thebanana3.Location = new Point(thebanana4.Location.X, thebanana4.Location.Y);//把篮子右边的香蕉拿走了
                thebanana4.Visible = true;
                thebanana3.Visible = false;
                for (int i = 0; i < n; i++)//拿着香蕉原路返回
                {
                    x = theson.Location.X - move_x;
                    y = theson.Location.Y - move_y;
                    bx = thebanana4.Location.X - move_x;
                    by = thebanana4.Location.Y - move_y;
                    theson.Location = new Point(x, y);
                    thebanana4.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
            }
        }

        public void Son_eat()//儿子吃香蕉
        {
            pictureBox2.Visible = true;//吃香蕉
            Thread.Sleep(1000);
            thebanana4.Visible = false;
            pictureBox2.Visible = false;
        }

        public void Daughter_move()//女儿取草莓
        {
            int x, y, bx, by;
            int move_x, move_y;//步长
            int n = 10;
            pictureBox3.Visible = false;
            thestrawberry4.Visible = false;
            if (thestrawberry2.Visible == true)//篮子左边有草莓
            {
                move_x = -10;
                move_y = -9;
                for (int i = 0; i < n; i++)
                {
                    x = thedaughter.Location.X + move_x;
                    y = thedaughter.Location.Y + move_y;
                    bx = thestrawberry4.Location.X + move_x;
                    by = thestrawberry4.Location.Y + move_y;
                    thedaughter.Location = new Point(x, y);
                    thestrawberry4.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
                thestrawberry2.Location = new Point(thestrawberry4.Location.X, thestrawberry4.Location.Y);//把篮子左边的草莓拿走了
                thestrawberry4.Visible = true;
                thestrawberry2.Visible = false;
                for (int i = 0; i < n; i++)//拿着草莓原路返回
                {
                    x = thedaughter.Location.X - move_x;
                    y = thedaughter.Location.Y - move_y;
                    bx = thestrawberry4.Location.X - move_x;
                    by = thestrawberry4.Location.Y - move_y;
                    thedaughter.Location = new Point(x, y);
                    thestrawberry4.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
            }
            else if (thestrawberry3.Visible == true)//篮子右边有草莓
            {
                move_x = -4;
                move_y = -9;
                for (int i = 0; i < n; i++)
                {
                    x = thedaughter.Location.X + move_x;
                    y = thedaughter.Location.Y + move_y;
                    bx = thestrawberry4.Location.X + move_x;
                    by = thestrawberry4.Location.Y + move_y;
                    thedaughter.Location = new Point(x, y);
                    thestrawberry4.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
                thestrawberry3.Location = new Point(thestrawberry4.Location.X, thestrawberry4.Location.Y);//把篮子右边的草莓拿走了
                thestrawberry4.Visible = true;
                thestrawberry3.Visible = false;
                for (int i = 0; i < n; i++)
                {
                    x = thedaughter.Location.X - move_x;
                    y = thedaughter.Location.Y - move_y;
                    bx = thestrawberry4.Location.X - move_x;
                    by = thestrawberry4.Location.Y - move_y;
                    thedaughter.Location = new Point(x, y);
                    thestrawberry4.Location = new Point(bx, by);
                    Thread.Sleep(100);
                }
            }
        }

        public void Daughter_eat()//女儿吃草莓
        {
            pictureBox3.Visible = true;//吃草莓
            Thread.Sleep(1000);
            thestrawberry4.Visible = false;
            pictureBox3.Visible = false;
        }

        private void Stop_Click(object sender, EventArgs e)
        {
            Environment.Exit(0);
        }
    }
}

86c23cde30c74536bce15b1c8ff56485.png

运行结果

dda3a9a35a09481ebb4794d322ff3e7c.png

 

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值