进程同步程序设计

您所在的位置:网站首页 非母亲不可有一 进程同步程序设计

进程同步程序设计

2024-07-12 19:15| 来源: 网络整理| 查看: 265

吃水果问题

桌子上有一只盘子,最多可容纳两个水果,每次只能放入或者取出一个水果。爸爸专门向盘子中放苹果,妈妈专门向盘子中放橘子,儿子专门等待吃盘子中的橘子,女儿专门等吃盘子中的苹果。试编程实现爸爸、妈妈、儿子、女儿四个人之间的同步。 要求: (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包引实现多进程并行操作。

如有错误,敬请指正。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3