GIL解释器锁,线程补充

Gil全局解释器锁

GIL是一个互斥锁(存在于Cpython),保证数据的安全(以牺牲效率换区数据的安全性)
阻止同一个进程内多个线程同时执行(不能并行但是能够实现并发)
并发:发起来像是同时进行的
GIL全局解释器存在的原因是CPython解释器的内存管理不是线程安全的

同一个进程下多个线程不能实现并行但能实现并发,多个进程下的线程可以实现并行。
在IO密集的任务中
	多线程优势更为明显(开启的消耗资源少)
在计算密集的任务中
	多进程有优势(多CPU的优势可以提现)

# 计算密集型
from multiprocessing import Process
from threading import Thread
import os,time
def work():
    res=0
    for i in range(100):
        res*=i


if __name__ == '__main__':
    l=[]
    print(os.cpu_count())  # 本机为8核
    start=time.time()
    for i in range(8):
        # p=Process(target=work) #耗时9.252728939056396
        p=Thread(target=work) #耗时35.369622230529785
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop=time.time()
    print('run time is %s' %(stop-start))

#    IO密集型
from multiprocessing import Process
from threading import Thread
import threading
import os,time
def work():
    time.sleep(2)


if __name__ == '__main__':
    l=[]
    print(os.cpu_count()) #本机为8核
    start=time.time()
    for i in range(600):
        p=Process(target=work) #耗时4.699530839920044
        # p=Thread(target=work) #耗时2.054128885269165
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop=time.time()
    print('run time is %s' %(stop-start))

GIL全局解释器锁与普通的互斥锁的区别

对于不同的数据,要想保证安全,需要加不同的锁处理
GIL并不能保证数据的安全,它是对Cpython解释器加锁,针对的是线程,让其无法并行,保证的是同一进程下多个线程间的安全
线程的互斥锁保证的是数据的安全性
from threading import Thread,Lock
import time

mutex=Lock()
n=100
def task():
    global n
    mutex.acquire() #如果不加自定义的锁,那么所有进程都得到了t=100的数据
    t=n   #确保t得到的是修改后的n
    time.sleep(0.1)
    n=t-1
    mutex.release()

lis=[]    
for i in range(100):
    q=Thread(target=task)
    q.start()
    lis.append(q)
for i in lis:
    i.join()
print(n)
    

死锁与递归锁

死锁就是两个线程或多个线程,得到了另一方需要获取的锁,而自身锁无法释放,导致线程的阻塞。
递归锁就是,可以重复获取的锁(自定义锁只能获取(acquire)一次),每一次获取都会计数+1,直到计数为0的时候,锁才会释放,其他线程才可以抢锁。
#死锁例子
from threading import Thread,Lock
import time

mutexA=Lock()
mutexB=Lock()

def task(name):
    mutexA.acquire()#后来线程抢占了A锁,但是B锁未得到释放,无法获取
    print('A get',name)
    mutexB.acquire()
    print('B get',name)
    mutexA.release()
    print('A lose',name)
    mutexB.release()
    print('B lose',name)
    f1(name)
def f1(name):
    mutexB.acquire()
    print('B get',name)
    time.sleep(0.1) #在IO的时候,其他的线程已经抢占了A锁,而B锁并未释放
    mutexA.acquire()
    print('A get',name)
    mutexA.release()
    print('A lose',name)
    mutexB.release()
    print('B lose',name)
    
if __name__ == '__main__':
	for i in range(100):
    	p=Thread(target=task,args=(i,))
        p.start()
#递归锁
from threading import Thread,RLock
import time
mutex=RLock()#生成一个递归锁对象

class MyThread(Thread):
    def run(self):
        self.f1()
        self.f2()
	def f1(self):
        mutex.acquire()
        print(self.name,1)
        mutex.acquire()
        print(self.name,2)
        mutex.release()
        mutex.release()
	def f2(self):
        mutex.acquire()
        print(self.name,3)
        time.sleep(0.5)
        mutex.acquire()
        print(self.name,4)
        mutex.release()
        mutex.release()

if __name__ == '__main__':
    for i in range(100):
        p = MyThread()
        p.start() 
        
    
    

信号量

#抢占厕所的例子
from threading import Thread,Semaphore
import time
sm=Semaphore(5)#设定信号量为5,只能有5个线程可以继续执行

def task(name):
    with sm:
    	print('%s 正在上厕所')
        time.sleep(5)

if __name__=='__main__':
    for i in range(20):
        p=Thread(target=task,args=(i,))
        p.start()

event时间

from threading import Event,Thread
import time

event=Event()

def light():
    print('红灯亮了')
    time.sleep(5)
    event.set() #解除阻塞
    print('绿灯亮了')
def car(i):
    print('%s 正在等红灯'%i)
    event.wait() #阻塞
    print('%s 通行'%i)
    
if __name__=='__main__':
    t=Thread(target=light)
    t.start()
    for i in range(10):
        c=Thread(target=car,args=(i,))
        c.start()

线程queue

import queue
q=queue.Queue(3)#Queue按照队列,先进先出
q.put(1)
q.put(2)
q.put(3)
print(q.get())
print(q.get())
print(q.get())

q = queue.LifoQueue(5)#堆栈,Lifo,last in first out 先进后出
q.put(1)
q.put(2)
q.put(3)
q.put(4)
print(q.get())

q = queue.PriorityQueue()#PriorityQueue,优先级,数据越小,优先级越高
q.put((10,'a'))  
q.put((-1,'b'))
q.put((100,'c'))
print(q.get())
print(q.get())
print(q.get())
# -1<10<100,所以顺序是(-1, 'b'),(10, 'a'),(100, 'c')
posted @ 2019-05-08 16:52  Mr-Bear  阅读(108)  评论(0编辑  收藏  举报