JasonYeung 2020-03-27
一、锁的作用
锁的作用是:使进程产生同步,确保数据的一致性。
二、线程安全和非线程安全
a = 1 ,两个线程分别给a加一次1,理想结果是 a = 3(线程安全)
如果两个线程同时拿到a=1的状态,分别加上1,那么a = 2(非线程安全)
非线程安全转换为线程安全时,就需要在非线程安全上加上锁
三、代码
# 锁1 (Lock:给一个进程指定一把锁)
from multiprocessing import Process
import time
def l(num):
time.sleep(0.2)
print("Hello Num: %s" % (num))
time.sleep(0.2)
print("Hello Num: %s" % (num))
time.sleep(0.2)
print("Hello Num: %s" % (num))
if __name__ == ‘__main__‘:
for num in range(50):
Process(target=l, args=(num,)).start()
结果:
Hello Num: 0
Hello Num: 1
Hello Num: 5
Hello Num: 43
Hello Num: 22
Hello Num: 6
。
。
。
Hello Num: 31
Hello Num: 28
Hello Num: 35
Hello Num: 48
Hello Num: 26
Hello Num: 27
# 结论:没有锁的情况下,子进程拿到数字就会去执行任务,导致打印的数字没有顺序
# 用函数的方式加锁
from multiprocessing import Process, Lock
import time
def l(lock, num):
lock.acquire() # 获得锁
time.sleep(0.02)
print("Hello Num: %s" % (num))
time.sleep(0.02)
print("Hello Num: %s" % (num))
time.sleep(0.02)
print("Hello Num: %s" % (num))
lock.release() # 释放锁
if __name__ == ‘__main__‘:
lock = Lock() # 创建一个共享锁实例
for num in range(50):
Process(target=l, args=(lock, num)).start()
结果:
Hello Num: 15
Hello Num: 15
Hello Num: 15
Hello Num: 13
Hello Num: 13
Hello Num: 13
。
。
。
Hello Num: 37
Hello Num: 37
Hello Num: 37
Hello Num: 23
Hello Num: 23
Hello Num: 23
# 结论:上了锁之后,子进程拿到数字后要等前边的进程出来了,释放了锁它才能进去执行,所有执行结果3个打印是一样的。
# 通过类的方式进行加锁的操作
import time
from multiprocessing import Process, Value, Lock
class Counter(object):
def __init__(self, initval=0):
self.val = Value(‘i‘, initval) # 全局共享变量,i 是指整型,d 是指双精度小鼠
self.lock = Lock() # 初始化了一个锁
def increment(self): # 在加锁的情况下,进行数字累加1
with self.lock: # 这个是加锁操作
self.val.value += 1 # 共享变量自加1
# print("increment one time!",self.value())
# 加此句死锁
def value(self): # 读取的时候也是加锁的
with self.lock: # 这个是加锁操作,和上面那个的区别是:这个是加锁和释放锁都是自动完成的。
return self.val.value
def func(counter):
for i in range(50):
time.sleep(0.01)
counter.increment()
if __name__ == ‘__main__‘:
counter = Counter(0)
procs = [Process(target=func, args=(counter,)) for i in range(10)]
for p in procs: p.start()
for p in procs: p.join()
print(counter.value())
结果:
500# 锁2:(Semaphore:给多个进程上多把锁,就是限制几个进程可以同时并发)
import multiprocessing
import time
def worker(s, i):
s.acquire() # 加锁
print(multiprocessing.current_process().name + " acquire")
time.sleep(i)
print(multiprocessing.current_process().name + " release")
s.release() # 释放锁
if __name__ == "__main__":
# 设置限制最多3个进程同时访问共享资源
s = multiprocessing.Semaphore(3)
for i in range(5):
p = multiprocessing.Process(target=worker, args=(s, i * 2))
p.start()
结果:
Process-1 acquire
Process-1 release
Process-3 acquire
Process-2 acquire
Process-2 release
Process-4 acquire
Process-3 release
Process-5 acquire
Process-4 release
Process-5 release