◆问题描述
两个人下棋,一方执黑棋,一方执白棋。要求双方轮流下子。给出两种情况的解决办法:
1)执黑子一方先下
2)双方都可以先下,谁先抢到棋盘谁先下。然后开始轮流下子。
第一种情况
1)
贴代码:
import threading
import time
import random
b=threading.Semaphore(1)
w=threading.Semaphore(0)
def black():
global b,w
i=0
while(i<5):
b.acquire()
i+=1
print("black! ")
print(i)
w.release()
time.sleep(random.random())
def white():
global b,w
j=0
while(j<5):
w.acquire()
j+=1
print("white! ")
print(j)
b.release()
time.sleep(random.random())
if __name__=='__main__':
black=threading.Thread(name='Black',target=black)
white=threading.Thread(name='White',target=white)
black.start();
white.start();
运行结果:
第二种情况
2)
贴代码
import threading
import random
import time
s=threading.Semaphore(1)
lock=threading.Lock()
def black():
global bfg,wfg
i=0
fg=False
s.acquire()
if fg is not True:
bfg = threading.Semaphore(1)
wfg = threading.Semaphore(0)
fg=True
s.release()
while(i<5):
bfg.acquire()
if lock.acquire():
i+=1
print("black!")
wfg.release()
lock.release()
else:
wfg.release()
break
time.sleep(random.random())
def white():
global bfg, wfg
j = 0
fg = False
s.acquire()
if fg is not True:
bfg = threading.Semaphore(0)
wfg = threading.Semaphore(1)
fg = True
s.release()
while (j < 5):
wfg.acquire()
if lock.acquire():
j += 1
print("white!")
bfg.release()
lock.release()
else:
bfg.release()
break
time.sleep(random.random())
if __name__ =='__main__':
black = threading.Thread(name='Black', target=black)
white = threading.Thread(name='White', target=white)
a=random.randint(0,9)
print(a)
if(a<=4):
black.start()
white.start()
else:
white.start()
black.start()
运行结果:
PS:
引用-->对于Python的解释:
作者:DarrenChan陈驰
链接:https://www.zhihu.com/question/23474039/answer/269526476
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Python中的多线程是假的多线程! 为什么这么说,我们先明确一个概念,全局解释器锁(GIL)。
Python代码的执行由Python虚拟机(解释器)来控制。Python在设计之初就考虑要在主循环中,同时只有一个线程在执行,就像单CPU的系统中运行多个进程那样,内存中可以存放多个程序,但任意时刻,只有一个程序在CPU中运行。同样地,虽然Python解释器可以运行多个线程,只有一个线程在解释器中运行。
对Python虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同时只有一个线程在运行。在多线程环境中,Python虚拟机按照以下方式执行。
1.设置GIL。
2.切换到一个线程去执行。
3.运行。
4.把线程设置为睡眠状态。
5.解锁GIL。
6.再次重复以上步骤。
对所有面向I/O的(会调用内建的操作系统C代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待I/O的时候运行。如果某线程并未使用很多I/O操作,它会在自己的时间片内一直占用处理器和GIL。也就是说,I/O密集型的Python程序比计算密集型的Python程序更能充分利用多线程的好处。
我们都知道,比方我有一个4核的CPU,那么这样一来,在单位时间内每个核只能跑一个线程,然后时间片轮转切换。但是Python不一样,它不管你有几个核,单位时间多个核只能跑一个线程,然后时间片轮转。看起来很不可思议?但是这就是GIL搞的鬼。任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。通常我们用的解释器是官方实现的CPython,要真正利用多核,除非重写一个不带GIL的解释器。