from threading import Thread
import os, time
count = 0
def work():
global count
temp = count
time.sleep(0.1)
count = temp + 1
def main():
t = []
for i in range(100):
p = Thread(target=work)
t.append(p)
p.start()
for p in t:
p.join()
if __name__ == '__main__':
main()
print('count = ', count) #count = 1
from threading import Thread, Lock, current_thread
import time
count = 0
def work():
global count
#未加锁的代码并发执行
time.sleep(2)
print('%s start to run' % current_thread().getName())
lock.acquire()
# 加锁的代码串行执行
temp = count
time.sleep(0.5)
count = temp + 1
lock.release()
def main():
t = []
for i in range(100):
p = Thread(target=work)
t.append(p)
p.start()
p.join()
#for p in t:
#p.join()
if __name__ == '__main__':
lock = Lock()
start = time.time()
main()
end = time.time()
print('count =', count) #n: 100
print('time =', (end - start)) #time= 52 和 250
p.start()后立即接join(),work函数内所有代码为串行执行,time大概值为250;
加锁过后,仅是加锁的部分代码为串行,效率更高,time大概值为50;
死锁
两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去
from threading import Thread, Lock, RLock
import time
class MyThread(Thread):
def run(self):
self.func1()
self.func2()
def func1(self):
l1.acquire()
print('%s得到l1.' % self.name)
l2.acquire()
print('%s得到l2.' % self.name)
l1.release()
l2.release()
def func2(self):
l2.acquire()
print('%s得到l2.' % self.name)
time.sleep(1)
l1.acquire()
print('%s得到l1.' % self.name)
l1.release()
l2.release()
def main():
for i in range(5):
t = MyThread()
t.start()
if __name__ == '__main__':
l1 = Lock()
l2 = Lock()
#l1 = l2 = RLock()
main()
结果:
解决方案
l1 = l2 = RLock()
Lock是阻塞其他线程对共享资源的访问,且同一线程只能acquire一次,如多于一次就出现了死锁,程序无法继续执行。RLock允许在同一线程中被多次acquire,既保证线程对共享资源的独占,又避免死锁的出现。线程对共享资源的释放需要把所有锁都release。即n次acquire,需要n次release。