2019/09/18 学习整理
并发编程
线程锁
多个线程抢占资源的情况
from threading import Thread
import os, time
def work():
global n
temp = n
time.sleep(0.1)
n = temp - 1
if __name__ == '__main__':
n = 100
l = []
for i in range(100):
p = Thread(target=work)
l.append(p)
p.start()
for p in l:
p.join()
print(n) # 结果可能为99
使用线程锁解决线程修改数据混乱问题。
加锁后
from threading import Thread,Lock
import os,time
def work():
global n
lock.acquire()
temp=n
time.sleep(0.1)
n=temp-1
lock.release()
if __name__ == '__main__':
lock=Lock()
n=100
l=[]
for i in range(100):
p=Thread(target=work)
l.append(p)
p.start()
for p in l:
p.join()
print(n) #结果肯定为0,由原来的并发执行变成串行,牺牲了执行效率保证了数据安全
死锁问题
死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
from threading import Lock as Lock
import time
mutexA=Lock()
mutexA.acquire()
mutexA.acquire()
print(123)
mutexA.release()
mutexA.release()
解决办法就是用递归锁
递归锁(RLock)
在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock
这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁
from threading import RLock as Lock
import time
mutexA=Lock()
mutexA.acquire()
mutexA.acquire()
print(123)
mutexA.release()
mutexA.release()
信号量Semaphore
Semaphore管理一个内置的计数器,
每当调用acquire()时内置计数器-1;
调用release() 时内置计数器+1;
计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。
实例:(同时只有5个线程可以获得semaphore,即可以限制最大连接数为5):
from threading import Thread,Semaphore
import threading
import time
def task():
sm.acquire()
print(f"{threading.current_thread().name} get sm")
time.sleep(3)
sm.release()
if __name__ == '__main__':
sm = Semaphore(5) # 同一时间只有5个进程可以执行。
for i in range(20):
t = Thread(target=task)
t.start()
与进程池是完全不同的概念,进程池Pool(4),最大只能产生4个进程,而且从头到尾都只是这四个进程,不会产生新的,而信号量是产生一堆线程/进程。
GIL
https://www.cnblogs.com/Wunsch/p/11542258.html
多线程与多进程
from threading import Thread
from multiprocessing import Process
import time
# 计算密集型
# def work1():
# res=0
# for i in range(100000000): #1+8个0
# res*=i
#
# if __name__ == '__main__':
# t_list = []
# start = time.time()
# for i in range(4):
# # t = Thread(target=work1)
# t = Process(target=work1)
# t_list.append(t)
# t.start()
# for t in t_list:
# t.join()
# end = time.time()
# # print('多线程',end-start) # 多线程 15.413789510726929
# print('多进程',end-start) # 多进程 4.711405515670776
# # io密集型
# def work1():
# x = 1+1
# time.sleep(5)
#
#
# if __name__ == '__main__':
# t_list = []
# start = time.time()
# for i in range(4):
# t = Thread(target=work1)
# # t = Process(target=work1)
# t_list.append(t)
# t.start()
# for t in t_list:
# t.join()
# end = time.time()
# print('多线程',end-start) # 多线程 5.002625942230225
# # print('多进程',end-start) # 多进程 5.660863399505615