日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

python?包之?threading?多線程_python

作者:autofelix ? 更新時間: 2022-06-06 編程語言

一、創建一個線程

  • 通過實例化threading.Thread類創建線程
import threading

def func(s):
print(s)

if __name__ == '__main__':
# 創建線程
thread = threading.Thread(target=func, args=('hello',))
# 啟動線程
thread.start()
# 等待線程結束
thread.join()

二、創建多個線程

import threading

def func(s):
print(s)

if __name__ == '__main__':
thread = [
threading.Thread(target=func, args=('1', ))
threading.Thread(target=func, args=('2', ))
]

[t.start() for t in thread]
[t.join() for t in thread]

三、線程同步

  • 使用鎖實現線程同步
  • threading.Lock是直接通過_thread模塊擴展實現的
  • 鎖只有“鎖定”和“非鎖定”兩種狀態
  • 同一個線程獲取鎖后,如果在釋放鎖之前再次獲取鎖會導致當前線程阻塞,除非有另外的線程來釋放鎖,如果只有一個線程,并且發生了這種情況,會導致這個線程一直阻塞下去,即形成了死鎖。
import time
import threading

# 創建鎖
lock = threading.Lock()
# 全局變量
global_resource = [None] * 5

def change_resource(para, sleep):
# 請求鎖
lock.acquire()
# 這段代碼如果不加鎖,第一個線程運行結束后global_resource中是亂的,輸出為:結果是: ['hello', 'hi', 'hi', 'hello', 'hello']
# 第二個線程運行結束后,global_resource中還是亂的,輸出為:結果是: ['hello', 'hi', 'hi', 'hi', 'hi']
global global_resource
for i in range(len(global_resource)):
global_resource[i] = para
time.sleep(sleep)
print("結果是:", global_resource)

# 釋放鎖
lock.release()

if __name__ == '__main__':
thread = [
threading.Thread(target=change_resource, args=('hi', 2))
threading.Thread(target=change_resource, args=('hello', 1))
]

[t.start() for t in thread]
[t.join() for t in thread]

# 結果是: ['hi', 'hi', 'hi', 'hi', 'hi']
# 結果是: ['hello', 'hello', 'hello', 'hello', 'hello']

四、遞歸鎖

  • 上面線程同步使用的是普通鎖,也就是只有鎖的狀態,并不知道是哪個線程加的鎖
  • 這樣的話使用普通鎖時,對于一些可能造成死鎖的情況,可以考慮使用遞歸鎖來解決
  • 遞歸鎖和普通鎖的差別在于加入了“所屬線程”和“遞歸等級”的概念
  • 釋放鎖必須有獲取鎖的線程來進行釋放
import time
import threading

# 使用成一個遞歸鎖就可以解決當前這種死鎖情況
rlock_hi = rlock_hello = threading.RLock()

def test_thread_hi():
# 初始時鎖內部的遞歸等級為1
rlock_hi.acquire()
print('線程test_thread_hi獲得了鎖rlock_hi')
time.sleep(2)
# 如果再次獲取同樣一把鎖,則不會阻塞,只是內部的遞歸等級加1
rlock_hello.acquire()
print('線程test_thread_hi獲得了鎖rlock_hello')
# 釋放一次鎖,內部遞歸等級減1
rlock_hello.release()
# 這里再次減,當遞歸等級為0時,其他線程才可獲取到此鎖
rlock_hi.release()

def test_thread_hello():
rlock_hello.acquire()
print('線程test_thread_hello獲得了鎖rlock_hello')
time.sleep(2)
rlock_hi.acquire()
print('線程test_thread_hello獲得了鎖rlock_hi')
rlock_hi.release()
rlock_hello.release()

if __name__ == '__main__':
thread = [
threading.Thread(target=test_thread_hi)
threading.Thread(target=test_thread_hello)
]

[t.start() for t in thread]
[t.join() for t in thread]

五、信號鎖

  • 一個信號量管理一個內部計數器
  • acquire()方法會減少計數器,release()方法則增加計數器
  • 計數器的值永遠不會小于零
  • 當調用acquire()時,如果發現該計數器為零,則阻塞線程
  • 直到調用release()方法使計數器增加。
import time
import threading

# 創建信號量對象,初始化計數器值為3
semaphore3 = threading.Semaphore(3)


def thread_semaphore(index):
# 信號量計數器減1
semaphore3.acquire()
time.sleep(2)
print('thread_%s is running...' % index)
# 信號量計數器加1
semaphore3.release()


if __name__ == '__main__':
# 雖然會有9個線程運行,但是通過信號量控制同時只能有3個線程運行
# 第4個線程啟動時,調用acquire發現計數器為0了,所以就會阻塞等待計數器大于0的時候
for index in range(9):
threading.Thread(target=thread_semaphore, args=(index, )).start()

原文鏈接:https://blog.51cto.com/autofelix/5167799

欄目分類
最近更新