多线程-互斥锁
从例子出发,来看需求:
n=100, 启动100个线程,每个线程对n-1,运行完后输出最后结果。
来看我们一般的做法:
这儿已n=3为例:
from threading import Thread
import time
n = 3
def task():
global n
temp = n
time.sleep(0.1)
n = temp - 1
if __name__ == '__main__':
t1 = Thread(target=task)
t2 = Thread(target=task)
t3 = Thread(target=task)
t1.start()
t1.join()
t2.start()
t2.join()
t3.start()
t3.join()
print("主,n=%s" % n)
输出:
主,n=0
这里达到了我们的要求,但是这是串行了,并没有提高效率。
改进一下,其实也是串行:
from threading import Thread
import time
n = 3
def task():
global n
temp = n
time.sleep(0.1)
n = temp - 1
if __name__ == '__main__':
for i in range(3):
t = Thread(target=task)
t.start()
t.join()
print("主,n=%s" % n)
输出:
主,n=0
这里其实也是串行,只不过写成了for循环。
来看看Teacher讲的例子:
from threading import Thread
import time
n = 100
def task():
global n
temp = n
time.sleep(0.1)
n = temp - 1
if __name__ == '__main__':
t_l = []
for i in range(100):
t = Thread(target=task)
t_l.append(t)
t.start()
for t in t_l:
t.join()
print("主", n)
输出:
主 99
为什么会输出 99 呢 ?通过我的前两个串行的例子应该可以知道,要想做到每个线程都减1的情况,处理使用互斥锁,就只能写为串行,而这个例子咋眼一看没啥问题,实际上是有问题的,程序启动100个线程就开启了,当第1个线程启动后,就执行了真正的代码 global n 和 temp =n, 随后开始睡觉,睡的这期间其他的99个线程也是同样的进入到睡觉状态,当第1个线程执行完后便将temp -1 的结果给了n,也就是99,由于其他99个线程都经历了睡觉等待,所以都拿到的是temp=100,在睡觉完成后,都是执行的 temp - 1 即将99给到n,所以最后输出n为99。
需要注意的是,这里不是有join吗,为啥不是一个线程执行结束后再执行下一个线程呢,因为join在100个线程start之后,并不是每启动1个线程就开始join所以是没有用的,这里也是启动的100个join,只是保证100个线程后运行结束了再运行主线程。
那么怎么在不串行的情况下来实现这个功能呢,那就使用互斥锁:
from threading import Thread, Lock
import time
n = 100
def task():
global n
mutex.acquire()
temp = n
time.sleep(0.1)
n = temp - 1
mutex.release()
if __name__ == '__main__':
mutex = Lock()
t_l = []
for i in range(100):
t = Thread(target=task)
t_l.append(t)
t.start()
for t in t_l:
t.join()
print("主", n)
输出:
主 0
结果达到了我们的需求,同时牺牲了一定的效率,但保证了数据安全,互斥锁的使用使得程序内部只是局部串行,而不是全部的串行,只在需要的地方加锁,任务完成后解锁,让下一个任务继续执行。
共有 0 条评论