1. 程式人生 > >進程與線程2

進程與線程2

時間 子線程 釋放 __main__ 每一個 發生 臨時 rt thread ***

有了GIL還是會出現數據不安全,所以還是要用鎖

import time

from threading import Thread,Lock

n = 100

def func(lock):

  global n

  with lock:

    tmp = n-1

    n = tmp

l = []

lock = Lock()

for i in range(100):

  t = Thread(target = func,args = (lock,))

  t.smxtart()

  l.append(t)

for t in l:t.join()

print(n)

dis模塊(判斷數據是否安全)

import dis

n = 1

def func():

  n = 100

  n -= 1

dis.dis(func)

死鎖現象

  死鎖不是時刻發生的,有偶然的情況,每一個線程中不止一把鎖,並且套著使用

解決死鎖的方案

  如果某一件事情需要兩個資源同時出現,那麽不應該將兩個資源通過兩把鎖控制,而是看做是一個資源,用一把鎖控制,先臨時解決,然後找到死鎖原因,再去修改(科學家吃面條)(遞歸鎖也能解決死鎖現象)。

出現死鎖現象

# def eat1(name):
# noodle_lock.acquire()
# print(‘%s拿到面條了‘%name)
# fork_lock.acquire()
# print(‘%s拿到叉子了‘%name)
# print(‘%s開始吃面‘%name)
# time.sleep(0.2)
# fork_lock.release()
# print(‘%s放下叉子了‘ % name)
# noodle_lock.release()
# print(‘%s放下面了‘ % name)
#
# def eat2(name):
# fork_lock.acquire()
# print(‘%s拿到叉子了‘ % name)
# noodle_lock.acquire()
# print(‘%s拿到面條了‘ % name)
# print(‘%s開始吃面‘ % name)
# time.sleep(0.2)
# noodle_lock.release()
# print(‘%s放下面了‘ % name)
# fork_lock.release()
# print(‘%s放下叉子了‘ % name)
#
# Thread(target=eat1,args=(‘alex‘,)).start()
# Thread(target=eat2,args=(‘wusir‘,)).start()
# Thread(target=eat1,args=(‘太白‘,)).start()
# Thread(target=eat2,args=(‘寶元‘,)).start()
解決死鎖
# lock = Lock()
# def eat1(name):
# lock.acquire()
# print(‘%s拿到面條了‘%name)
# print(‘%s拿到叉子了‘%name)
# print(‘%s開始吃面‘%name)
# time.sleep(0.2)
# lock.release()
# print(‘%s放下叉子了‘ % name)
# print(‘%s放下面了‘ % name)
#
# def eat2(name):
# lock.acquire()
# print(‘%s拿到叉子了‘ % name)
# print(‘%s拿到面條了‘ % name)
# print(‘%s開始吃面‘ % name)
# time.sleep(0.2)
# lock.release()
# print(‘%s放下面了‘ % name)
# print(‘%s放下叉子了‘ % name)
#
# Thread(target=eat1,args=(‘alex‘,)).start()
# Thread(target=eat2,args=(‘wusir‘,)).start()
# Thread(target=eat1,args=(‘太白‘,)).start()
# Thread(target=eat2,args=(‘寶元‘,)).start()



遞歸鎖(RLock)
在同一個線程中可以無限次acquire,但是要想在其他線程中也acquire,必須先在自己線程中添加和acquire次數相同的release
import time
noodle_lock = fork_lock = RLock()
def eat1(name):
  noodle_lock.acquire()
  print(‘%s拿到了面條‘%name)
  frok_lock.aquire()
  print(‘%s拿到了叉子‘%name)
  print(‘%s開始吃面‘%name)
  time.sleep(0.2)
  fork_lock.release()
  print(‘%s放下叉子‘%name)
  noodle_lock.release()
  print(‘%s放下面條‘%name)
def eat2(name):
  fork_lock.acquire()
  print(‘%s拿到了叉子‘%name)
  noodle_lock.acquire()
  print(‘%s拿到了面條‘%name)
  print(‘%s開始吃面‘%name)
  time.sleep(0.2)
  fork_lock.release()
  print(‘%s放下叉子‘%name)
  noodle_lock.release()
  print(‘%s放下面條‘%name)
Thread(target = eat1,args = (‘alex‘,)).start()
Thread(target = eat1,args = (‘wusir‘,)).start()
Thread(target = eat1,args = (‘taibai‘,)).start()
Thread(target = eat1,args = (‘baiyuan‘,)).start()

線程 信號量(Semaphore)
import time
from threading import Semaphore,Thread

def func(name,sem):
sem.acquire()
print(name,‘start‘)
time.sleep(1)
print(name,‘stop‘)
sem.release()

sem = Semaphore(5)
for i in range(20):
Thread(target=func,args=(i,sem)).start()
進程池
  有1000個任務,一個進程池中有5個進程,所有的1000個任務會多次利用這五個進程來完成任務
信號量
  有1000個任務,有1000個線程、進程所有的1000個任務由於信號量的控制,只能5個5個的執行




線程事件 (Event)
  wait()阻塞 事件內部標識為True就停止阻塞
控制標識
  set #True
  clear  #False
  is_set #判斷是不是True


連接數據庫(用事件)
import time
import random
from threading import Thread,Event
def connect_sql(e):
count = 0
while count < 3:
e.wait(0.5)
if e.is_set():
print(‘連接數據庫成功‘)
break
else:
print(‘數據庫未連接成功‘)
count += 1
F
def test(e):
time.sleep(random.randint(0,3))
e.set()

e = Event()
Thread(target=test,args=(e,)).start()
Thread(target=connect_sql,args=(e,)).start()



線程條件()
  wait 阻塞
  notify(n) 給信號
  假如現在有20個線程,所有的線程都在wait這裏阻塞,nptify(n)n傳了多少,那麽wait這邊就能收獲得到多少個解除阻塞的通知

import threading

def run(n):
con.acquire()
con.wait()
print("run the thread: %s" % n)
con.release()

if __name__ == ‘__main__‘:

con = threading.Condition()
for i in range(10):
t = threading.Thread(target=run, args=(i,))
t.start()

while True:
inp = input(‘>>>‘)
if inp == ‘q‘:
break
con.acquire()
con.notify(int(inp))
con.release()
print(‘****‘)

設置某個條件
如果滿足這個條件 就可以釋放線程
監控測試我的網速
20000個任務
測試我的網速 /系統資源
發現系統資源有空閑,我就放行一部分任務




線程定時器(Timer)
from threading import Timer

def func():
print(‘執行我啦‘)

t = Timer(3,func)      #參數3為3秒,就是等待3秒在執行子線程
            # 現在這個時間點我不想讓它執行,而是預估一下大概多久之後它執行比較合適
t.start()
print(‘主線程的邏輯‘)




線程隊列(Queue) #先進先出
q = queue.Queue()
線程棧(LifoQueue)  #先進後出
lfq = queue.LifoQueue()   # 棧
lfq.put(1)
lfq.put(2)
lfq.put(3)
print(lfq.get())
print(lfq.get())
print(lfq.get())

優先級隊列(PriorityQueue) #根據第一個值的大小來排定優先級(ascii碼越小,優先級越高)
q = queue.PriorityQueue()
q.put((2,‘a‘))
q.put((1,‘c‘))
q.put((1,‘b‘))
print(q.get())

線程池
concurrent.futures




  
  

進程與線程2