鎖,threading local,以及生產者和消費者模型

Bound_w發表於2018-09-11

 

1.鎖:Lock(一次放行一個)

  執行緒安全,多執行緒操作時,內部會讓所有的執行緒排隊處理。

  執行緒不安全:+人=>排隊處理

  以後鎖程式碼塊

v=[]
lock=threading.Lock()#宣告鎖
def func(arg):
    lock.acquire()#上鎖
    v.append(arg)
    time.sleep(0.1)
    m=v[-1]
    print(arg,m)
    lock.release()#解鎖
for i in range(10):
    t=threading.Thread(target=func,args=(i,))
    t.start()
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9

 

2.鎖:Rlock(一次放一個)

  支援遞迴鎖,鎖多次

v = []
lock = threading.RLock()
def func(arg):
    lock.acquire()
    # lock.acquire()

    v.append(arg)
    time.sleep(0.01)
    m = v[-1]
    print(arg,m)

    lock.release()
    # lock.release()


for i in range(10):
    t =threading.Thread(target=func,args=(i,))
    t.start()
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9

 

3.一次放多個:BoundedSemaphore

  threading.BoundedSemaphore(指定一次放幾個就放幾個),訊號量

import time
import threading
lock=threading.BoundedSemaphore(5)#指定幾個就每次執行幾個執行緒
def func(arg):
    lock.acquire()
    print(arg)
    time.sleep(3)
    lock.release()
for i in range(20):
    t=threading.Thread(target=func,args=(i,))
    t.start()

 

4.條件鎖Condition(一次放指定個數,使用者輸入幾個就放幾個)******

方法一:
import
time import threading lock=threading.Condition()#宣告放的方式 def func(arg): lock.acquire() lock.wait()#上鎖 print(arg) time.sleep(2) lock.release() for i in range(20): t=threading.Thread(target=func,args=(i,)) t.start() while 1: user=int(input(">>>")) lock.acquire() lock.notify(user)#重點操作 lock.release()
方法二:
def xxx():
input('>>>')
return True
def func(arg):
lock.wait_for(xxx)
print(arg)
time.sleep(1)
for i in range(10):
t=threading.Thread(target=func,args=(i,))
t.start()

 

5.Event(一次放所有)

import threading
import time
lock=threading.Event()宣告一次放掉全部的執行緒
def func(arg):
lock.wait()加鎖紅燈
print(arg)
for i in range(10):
t=threading.Thread(target=func,args=(i,))
t.start()
input('>>>')
lock.set()解鎖綠燈
lock.clear()再次紅燈
for i in range(10):
t=threading.Thread(target=func,args=(i,))
t.start()
input('>>>')
lock.set()綠燈

 

 

總結:

  執行緒安全:列表和字典是執行緒安全的,佇列。

  為什麼要加鎖?

  非執行緒安全的可以人為加鎖,控制一段程式碼!

6.threading.local

作用:

  內部自動為每個執行緒維護一個空間(字典),用於當前存取屬於自己的值,保證執行緒之間的資料隔離。

應用:
import
threading import time v=threading.local() def func(arg): v.phone=arg time.sleep(2) print(v.phone,arg) for i in range(10): t=threading.Thread(target=func,args=(i,)) t.start()
原理:
import threading
import time
v=threading.local()
def func(arg):
v.phone=arg
time.sleep(2)
print(v.phone,arg)
for i in range(10):
t=threading.Thread(target=func,args=(i,))
t.start()

 

7.執行緒池:控制最多開指定的執行緒

import threading
from concurrent.futures import ThreadPoolExecutor
import time
def func(a1,a2):
    time.sleep(2)
    print(a1,a2)
pool = ThreadPoolExecutor(5)#建立執行緒池,最多5個執行緒
for i in range(20):
    #去執行緒池中申請一個執行緒,讓執行緒執行該函式
    pool.submit(func,i,20)

 

8.生產者消費者模型

import threading
import queue
import time
q=queue.Queue()#執行緒安全
def func(id):
    """
    生產者
    :param id:
    :return:
    """
    while 1:
        time.sleep(2)
        q.put('包子')
        print('廚子%s,做了一個包子' %id)
for i in range(1,5):
    t=threading.Thread(target=func,args=(i,))
    t.start()
def usera(id):
    """
    消費者
    :param id: 
    :return: 
    """
    while 1:
        q.get()
        print('第%s個顧客吃了一個包子' %id)
for i in range(1,8):
    t=threading.Thread(target=usera,args=(i,))
    t.start()

 

佇列:先進先出

擴充套件:

  棧:後進先出

內容補充:

執行緒池在python2中是沒有的,執行緒不能太多,會造成執行緒的上下切換,影響效率

程式和執行緒的區別?

1.程式是CPU資源分配的最小單元

執行緒是CPU計算的最小單元

2.一個程式中可以有多個執行緒,

3.對於python來說,程式執行緒和其他語言有差異,是由gill鎖造成的,gill鎖保證一個程式中,同一時刻只能有一個執行緒能被CPU排程

 

程式是進行資料隔離

執行緒是CPU工作的最小單元,共享程式中的所有資源,每個執行緒分擔一些任務,最終執行

相關文章