1. 程式人生 > >Python 3.7.1 模組 併發執行 底層執行緒API _thread

Python 3.7.1 模組 併發執行 底層執行緒API _thread

底層執行緒API


該模組提供了用於處理多執行緒(也稱為輕量級程序或任務)的低階原語- 多個控制執行緒共享其全域性資料空間。為了同步,提供了簡單的鎖(也稱為互斥鎖或二進位制訊號量)。 threading模組提供了一個基於此模組構建的更易於使用和更高級別的執行緒API。

版本3.7中已更改:此模組曾經是可選的,現在始終可用。

1._thread 函式

該模組定義了以下常量和函式:

exception _thread.error

引發特定於執行緒的錯誤。

在版本3.3中更改:現在是內建RuntimeError的同義詞。

_thread.LockType

這是鎖定物件的鎖的型別。

_thread.start_new_thread(function, args[, kwargs])

啟動一個新執行緒並返回其識別符號。執行緒使用引數列表args(必須是元組)執行function函式。可選的 kwargs引數指定關鍵字引數的字典。當函式返回時,執行緒將以靜默方式退出。當函式以未處理的異常終止時,將列印堆疊跟蹤,然後執行緒退出(但其他執行緒繼續執行)。

_thread.interrupt_main()

在主執行緒中引發KeyboardInterrupt異常。子執行緒可以使用此函式來中斷主執行緒。

_thread.exit()

引發SystemExit異常。未捕獲時,這將導致執行緒以靜默方式退出。

_thread.allocate_lock()

返回一個新的鎖物件。鎖的方法如下所述。鎖最初是非鎖定的。

_thread.get_ident()

返回當前執行緒的“執行緒識別符號”。這是一個非零整數。它的值沒有直接意義; 它旨在用作例如索引執行緒特定資料的字典的 magic cookie。當執行緒退出並建立另一個執行緒時,可以回收執行緒識別符號。

_thread.stack_size([size])

返回建立新執行緒時使用的執行緒堆疊大小。可選的 size引數指定用於後續建立的執行緒的堆疊大小,並且必須為0(使用平臺或已配置的預設值)或至少為32,768(32 KiB)的正整數值。如果未指定size,則使用0。如果不支援更改執行緒堆疊大小,則引發RuntimeError。如果指定的堆疊大小無效,則引發ValueError,堆疊大小未經修改。32 KiB是目前支援的最小堆疊大小值,以保證直譯器本身有足夠的堆疊空間。請注意,某些平臺可能對堆疊大小的值有特定限制,例如要求最小堆疊大小> 32 KiB或需要以系統記憶體頁面大小的倍數進行分配 - 應參考平臺文件以獲取更多資訊(4 KiB頁面很常見;在沒有更具體資訊的情況下,建議的方法是使用4096的倍數作為堆疊大小)。

可用性:Windows,具有POSIX執行緒的系統。

_thread.TIMEOUT_MAX

允許Lock.acquire()的timeout引數最大值。指定超過此值的超時將引發一個OverflowError。

版本3.2中的新功能。

2.lock函式

鎖物件具有以下方法:

lock.acquire(waitflag=1, timeout=-1)

在沒有任何可選引數的情況下,此方法無條件地獲取鎖,如果有必要,等待它被另一個執行緒釋放(一次只有一個執行緒可以獲取鎖定 - 這就是它們存在的原因)。

如果存在整數waitflag引數,則操作取決於其值:如果它為零,則僅在不等待的情況下立即獲取鎖定時獲取鎖定,而如果它非零,則如上所述無條件地獲取鎖定。

如果浮點型timeout引數存在且為正,則它指定返回之前的最長等待時間(以秒為單位)。負 timeout引數指定無限制等待。如果waitflag為零,則無法指定超時。

如果成功獲取鎖定則返回值True,否則 返回值False。

改變在3.2版本:該超時引數是新增加的。

在版本3.2中更改:現在可以通過POSIX上的訊號中斷鎖定獲取。

lock.release()

釋放鎖定。必須先獲取鎖,但不一定是同一個執行緒。

lock.locked()

返回鎖的狀態:如果已被某個執行緒獲取返回True, 如果沒有返回False。

3.其它

除了這些方法之外,還可以通過with語句使用鎖定物件 ,例如:

import _thread

a_lock = _thread.allocate_lock()

with a_lock:
    print("a_lock is locked while this executes")

注意事項:

  • 執行緒與中斷奇怪地互動:KeyboardInterrupt 異常將由任意執行緒接收。(當signal 模組可用時,中斷始終轉到主執行緒。)
  • 呼叫sys.exit()或丟擲SystemExit異常等同於呼叫_thread.exit()。
  • 無法在鎖定時中斷acquire()方法 - KeyboardInterrupt異常發生在鎖被accquired之後。
  • 當主執行緒退出時,系統決定其他執行緒是否存活!在大多數系統中,它們在不執行 try… finally子句或執行物件解構函式的情況下被終止。
  • 當主執行緒退出時,它不執行任何常規清理(除了try… finally子句被使用),並且不重新整理標準I / O檔案。

4.例項

這裡引用了網友的 例項,特此說明

#!/usr/bin/env python3
# coding:utf-8
from time import ctime
from time import sleep
import _thread

loops = [4, 2, 3, 5]


def loop(nloop, nsec, lock):    # 引數依次為:標識,睡眠時間,鎖物件
    print("start loop", nloop, 'at:', ctime())
    sleep(nsec)
    print("loop", nloop, "done at:", ctime())
    lock.release()  # 釋放鎖


def main():
    print('start at:', ctime())
    locks = []
    nloops = range(len(loops))

    for i in nloops:
        lock = _thread.allocate_lock()  # 分配鎖物件
        lock.acquire()  # 獲取鎖物件
        locks.append(lock)

    for i in nloops:
        _thread.start_new(loop, (i, loops[i], locks[i]))

    # 等待所有鎖被釋放
    for i in nloops:
        while(locks[i].locked()):
            pass
    print('all DONE at', ctime())


if __name__ == '__main__':
    main()