"""
线程一共有5个状态:创建,就绪/可运行状态,运行,阻塞/等待,完成/死亡
当线程创建出来后,就进入了可运行状态,等线程启动后,便到了运行阶段,运行完后,便会完成销毁或者运行的过程中异常导致中途退出
Semaphore()和Barrier()的实现:
上述代码我们同时创建了5个线程并启动,这5个线程执行函数时,遇到了Semaphore或Barrier的函数,Semaphore相当于只有3个通道,5个线程
遇到3个通道,这能是最快的3个线程过这三个通过,剩余的两个线程等待这三个线程执行完后才能过这个通道。而Barrier相当于只有1个通道,
但这个通道规定,必须三个线程同时通过,当5个线程来到这个通道,最快的三个线程组成一队进入这个通过,而后来的两个线程则一直在等待
前三个线程执行完毕,并等待另外一个线程的到来才能组队通过通道
为什么需要让线程等待? 除了我们控制并发数和组合数之外,等待的另外一个作用是在线程间交互中保持数据的准确性
"""
#举例:我们有一个函数,一个全局变量,函数的内容是多次循环对这个全局变量加一个定制数,在减去这个指定数,然后创建两个线程去执行这个函数
num = 0
def testRun(num2):
global num
for i in range(10000000):
num += num2
num -= num2
#
# if __name__ == "__main__":
# t1 = threading.Thread(target=testRun,args=(6,))
# t2 = threading.Thread(target=testRun,args=(6,))
# t1.start(),t2.start()
# t1.join(),t1.join()
# print("num:",num)
"""
执行后发现:有时候结果是0,而有时候结果是6,其原因是,线程是并发运行的,我们不知道那个线程快,那个线程慢,
当第一个线程刚执行num += num2,还未来的及执行num -= num2时,第二个线程已经执行了num += num2,周而复始,等两个线程执行完后,
便出来结果可能不为0的结果
要解决结果,就需要让其中一个线程等待另外一个线程执行完一次后在执行,保证他们执行完一次后结果为0
有几种方法可以做到:
1.添加锁,这种方式阻止了多线程的并发,让多线程暂时的变成单线程执行,效率大大降低,同时,若每个线程都有自己的锁,
当这个线程加锁,之后异常出错后,这个线程就被清理调用,但锁没有被开,其他的线程一直等待锁的解开,便造成了死锁,
锁的创建: threading.Lock()
如下:
"""
import threading
lock = threading.Lock()
num = 0
def run(n):
global num
for i in range(100000000):
# lock.acquire() #加锁
# try: #捕获异常,避免出现死锁
# num = num + n
# num = num - n
# finally:
# lock.release() #解锁
#锁的另外一种形式:自动上锁和解锁,可以减低死锁的概率
with lock:
num = num + n
num = num - n
# if __name__ == "__main__":
# t1 = threading.Thread(target=run,args=(6,))
# t2 = threading.Thread(target=run,args=(6,))
# t1.start(),t2.start()
# t1.join(),t1.join()
# print("num:",num)
"""
2.将全局变量变成线程的局部变量,这样每个线程有自己的局部变量,同时自己的局部变量在其他地方是调用不了,这样也确保了数据的准确性
如下:
"""
local = threading.local() #创建线程局部变量空间
num = 0
# def run(x,n):
# x = x + n
# x = x - n
def func(n):
local.x = num
for i in range(100000000):
local.x += n
local.x -= n
print("%s-%d" %(threading.current_thread().name,local.x))
# if __name__ == "__main__":
# t1 = threading.Thread(target=func,args=(6,))
# t2 = threading.Thread(target=func,args=(6,))
# t1.start(),t2.start()
# t1.join(),t1.join()