• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

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

武飞扬头像
一个丧乐的野指针
帮助1

吃水果问题

桌子上有一只盘子,最多可容纳两个水果,每次只能放入或者取出一个水果。爸爸专门向盘子中放苹果,妈妈专门向盘子中放橘子,儿子专门等待吃盘子中的橘子,女儿专门等吃盘子中的苹果。试编程实现爸爸、妈妈、儿子、女儿四个人之间的同步。
要求:
(1)水果、盘子均通过导入图片来实现可视化;
(2)放水果、拿水果均有动画显示,包括把水果拿到手上去放、放完空手回来等均通过的动画予以展示;
(3)执行顺序由并发控制机制决定,而非通过延时实现;
(4)要求界面美观、动作流畅。

界面运行截图

学新通
运行结果:
学新通

代码框架

以P,V操作的框架为基础,掌握在python中,P,V操作如何转变为代码,多进程并行操作如何执行,以及各种相应的锁的运用。

import threading,time,pygame


def daughter_eat(name):
    global num, capacity,apple,orange

    while True:
    #P,此操作减少信号量的内部变量, 如果此变量的值非负, 那么分配该资源的权限. 如果是负值, 那么线程被挂起, 直到有其他的线程释放资源.
        #判断桌子上是否有苹果,有则可以执行,否则此进程被挂起不能执行,直到变量值大于0,执行的同时拿起了一个苹果
        apple_lock.acquire()
    #V,信号量的内部变量增加, 在信号量等待队列中排在最前面的线程会拿到共享资源的权限.
        #释放一个进程,代表桌子上允许放一个水果
        num_lock.release()
        #互斥,不允许其他线程操作
        mutex.acquire()
        for i in range(50):
            screen.blit(background, (0, 0))
            if i >=45:
                if num == 2:
                    if apple == 2:
                        blitOne(appleim)
                    elif orange == 1:
                        blitOne(orangeim)

                elif num == 1:
                    pass
                    # if apple == 1:
                    #     pass
            blitPerson()
            screen.blit(daughter_hand, (490 - i, 350 - i))
            pygame.display.update()
        apple -= 1
        num -= 1
        print(name, "从桌子上拿走一个苹果")
        print("现在桌子上还有"   str(apple)   "苹果"   str(orange)   "橘子")
        #释放互斥,允许下一个进程进行
        mutex.release()
        time.sleep(3)


def son_eat(name):
    global num, capacity, apple, orange

    while True:
        # 判断桌子上是否有橘子,有则可以执行,否则此进程被挂起不能执行,直到变量值大于0,执行的同时拿起了一个橘子
        orange_lock.acquire()
        # 释放一个进程,代表桌子上允许放一个水果
        num_lock.release()
        # 互斥,不允许其他进程操作
        mutex.acquire()
        for i in range(50):
            screen.blit(background, (0, 0))
            if i >= 45:
                if num == 2:
                    if apple == 1:
                        blitTwo(appleim)
                    elif apple == 0:
                        blitTwo(orangeim)

                elif num == 1:
                    pass

            blitPerson()
            screen.blit(son_hand, (170 - i, 390   i))
            pygame.display.update()
        orange -= 1
        num -= 1

        print(name, "从桌子上拿走一个橘子")
        print("现在桌子上还有"   str(apple)   "苹果"   str(orange)   "橘子")
        mutex.release()
        time.sleep(3)


def father_put(name, fruit):
    global num, capacity, apple, orange

    while True:
        num_lock.acquire()
        apple_lock.release()
        mutex.acquire()
        print(name, "把", fruit, "放在盘子里面")
        for i in range(50):
            screen.blit(background, (0, 0))
            if i >= 45:
                if num == 0:
                    blitOne(appleim)
                elif num == 1:
                    if apple == 1:
                        blitOne(appleim)
                        blitTwo(appleim)
                    else:
                        blitOne(orangeim)
                        blitTwo(appleim)
            blitPerson()
            screen.blit(dad_hand, (140   i, 140   i))
            #更新部分软件界面显示
            pygame.display.update()
        apple  = 1
        num  = 1
        print("在爸爸放苹果之后,桌子上苹果的数量: "   str(apple)   " 桌子上橘子的数量: "   str(orange))
        mutex.release()
        #使放水果速度大于拿水果速度,不会卡顿
        time.sleep(2)


def mother_put(name, fruit):
    global num, capacity, apple, orange

    while True:
        #给是否能放水果上锁
        num_lock.acquire()
        #放橘子解锁
        orange_lock.release()
        #控制只有一个进程运行,不允许其他进程运行,达到互斥
        mutex.acquire()
        print(name, "把", fruit, "放在盘子里面")
        for i in range(50):
            screen.blit(background, (0, 0))
            if i >= 45:
                if num == 0:
                    blitOne(orangeim)
                elif num == 1:
                    if orange == 1:
                        blitOne(orangeim)
                        blitTwo(orangeim)
                    else:
                        blitOne(appleim)
                        blitTwo(orangeim)
            blitPerson()
            screen.blit(mom_hand, (510 - i, 140   i))
            pygame.display.update()
        orange  = 1
        num  = 1
        print("在妈妈放橘子之后,桌子上苹果的数量: "   str(apple)   " 桌子上橘子的数量: "   str(orange))
        # 互斥效果解除,下一个进程可执行
        mutex.release()
        time.sleep(2)


def blitOne(fruit):
    screen.blit(fruit, one_size)
    blitPerson()


def blitTwo(fruit):
    screen.blit(fruit, two_size)
    blitPerson()



def blitPerson():
    screen.blit(father, dad_size)
    screen.blit(mom, mom_size)
    screen.blit(son, son_size)
    screen.blit(daughter, daughter_size)


if __name__ == "__main__":


    background_image_filename = 'E:\python代码\picture\Table.png'
    apple_image_filename = 'E:\python代码\picture\Apple.png'
    orange_image_filename = 'E:\python代码\picture\orange1.png'
    mom_image_filename = 'E:\python代码\picture\Mom.png'
    father_image_filename = 'E:\python代码\picture\Father.png'
    son_image_filename = 'E:\python代码\picture\Son.png'
    daughter_image_filename = 'E:\python代码\picture\Daughter.png'
    dad_hand_image_filename = 'E:\python代码\picture\Hand1.png'
    mom_hand_image_filename = 'E:\python代码\picture\Hand1.png'
    son_hand_image_filename = 'E:\python代码\picture\Hand.png'
    daughter_hand_image_filename = 'E:\python代码\picture\Hand.png'

    # 初始化pygame
    pygame.init()

    # 所有相应位置
    one_size = (200, 300)
    two_size = (350, 300)
    dad_size = (10, 10)
    mom_size = (500, 10)
    son_size = (10, 450)
    daughter_size = (540, 450)
    dad_hand_size = (80, 45)
    mom_hand_size = (480, 110)

    screenSize = (650, 651)

    # 创建窗口
    screen = pygame.display.set_mode(screenSize, 0)

    # 设置标题
    pygame.display.set_caption('吃水果进程')

    # 加载图片并转换, 从文件加载新图片,创建一个新的 Surface  对象
    background = pygame.image.load(background_image_filename)
    appleim = pygame.image.load(apple_image_filename)
    orangeim = pygame.image.load(orange_image_filename)
    mom = pygame.image.load(mom_image_filename)
    father = pygame.image.load(father_image_filename)
    son = pygame.image.load(son_image_filename)
    daughter = pygame.image.load(daughter_image_filename)
    dad_hand = pygame.image.load(dad_hand_image_filename)
    mom_hand = pygame.image.load(mom_hand_image_filename)
    son_hand = pygame.image.load(son_hand_image_filename)
    daughter_hand = pygame.image.load(daughter_hand_image_filename)


    #当打印结果是交替打印时,但是如果需求是需要打印完一个线程的内容后,
    # 再去打印另一个线程的内容,就需要用到锁。不加锁打印结果:加了睡眠时间,所以每隔1秒会交替打印出a、b值
    mutex = threading.Lock()
    # 最大容量
    capacity = 2
    # 当前个数
    num = 0
    # 苹果个数
    apple = 0
    # 橘子个数
    orange = 0



    apple_lock = threading.Semaphore(0)#0个进程
    orange_lock = threading.Semaphore(0)
    #因为桌子上最多只能放两个水果最少不放水果,对应的最多也只能拿两个水果,最少不拿水果,所以此进程数是2而不是4
    num_lock = threading.Semaphore(2)#2个进程

    #创建 Thread 对象,然后让它们运行,每个 Thread 对象代表一个进程,在每个线程中我们可以让程序处理不同的任务
    mother_thread = threading.Thread(target=mother_put, args=["妈妈", "橘子"])
    father_thread = threading.Thread(target=father_put, args=["爸爸", "苹果"])
    son_thread = threading.Thread(target=son_eat, args=["儿子"])
    daughter_thread = threading.Thread(target=daughter_eat, args=["女儿"])

    #启动 Thread 对象

    mother_thread.start()
    time.sleep(1)
    father_thread.start()
    time.sleep(1)
    son_thread.start()
    time.sleep(2)
    daughter_thread.start()
    time.sleep(2)

学新通

图片从阿里矢量图标获取,总共有4个进程,因为每次只能进行一种操作,所以这四个进程都互斥,根据threading.Lock()与threading.Semaphore(2)的结合实现多进程运行且避免死锁的情况发生,通过time.sleep(2)造成延时效果,同时start()函数只能执行一次,不能手动强制停止,否则进程退出并行操作不再执行。

总结

用python语言来体现进程的运行比较直接简洁,通过pygame包引实现窗口的展示与动画,通过threading包引实现多进程并行操作。

如有错误,敬请指正。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggefcf
系列文章
更多 icon
同类精品
更多 icon
继续加载