成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

python多線程、鎖、event事件機(jī)制的簡單使用

lowett / 3632人閱讀

摘要:從調(diào)用方法啟動(dòng)線程,到方法執(zhí)行完畢或遇到未處理異常而中斷這段時(shí)間內(nèi),線程是激活的調(diào)用將會(huì)使主調(diào)線程堵塞,直到被調(diào)用線程運(yùn)行結(jié)束或超時(shí)。對象實(shí)現(xiàn)了簡單的線程通信機(jī)制,它提供了設(shè)置信號,清除信號,等待等用于實(shí)現(xiàn)線程間的通信。

線程和進(jìn)程
1、線程共享創(chuàng)建它的進(jìn)程的地址空間,進(jìn)程有自己的地址空間

2、線程可以訪問進(jìn)程所有的數(shù)據(jù),線程可以相互訪問

3、線程之間的數(shù)據(jù)是獨(dú)立的

4、子進(jìn)程復(fù)制線程的數(shù)據(jù)

5、子進(jìn)程啟動(dòng)后是獨(dú)立的 ,父進(jìn)程只能殺掉子進(jìn)程,而不能進(jìn)行數(shù)據(jù)交換

6、修改線程中的數(shù)據(jù),都是會(huì)影響其他的線程,而對于進(jìn)程的更改,不會(huì)影響子進(jìn)程

threading.Thread
Thread 是threading模塊中最重要的類之一,可以使用它來創(chuàng)建線程。有兩種方式來創(chuàng)建線程:一種是通過繼承Thread類,重寫它的run方法;另一種是創(chuàng)建一個(gè)threading.Thread對象,在它的初始化函數(shù)(__init__)中將可調(diào)用對象作為參數(shù)傳入。

先來看看通過繼承threading.Thread類來創(chuàng)建線程的例子:

import threading
import time

class MyThread(threading.Thread):
    def __init__(self, arg):
        # super(MyThread, self).__init__() # 新式類繼承原有方法寫法
        threading.Thread.__init__(self)
        self.arg = arg

    def run(self):
        time.sleep(2)
        print(self.arg)

for i in range(10):
    thread = MyThread(i)
    print(thread.name)
    thread.start()

另外一種創(chuàng)建線程的方法:

import threading
import time

def process(arg):
    time.sleep(2)
    print(arg)

for i in range(10):
    t = threading.Thread(target=process, args=(i,))
    print(t.name)
    t.start()
Thread類還定義了以下常用方法與屬性:
Thread.getName() 獲取線程名稱
Thread.setName() 設(shè)置線程名稱
Thread.name 線程名稱

Thread.ident 獲取線程的標(biāo)識符。線程標(biāo)識符是一個(gè)非零整數(shù),只有在調(diào)用了start()方法之后該屬性才有效,否則它只返回None

判斷線程是否是激活的(alive)。從調(diào)用start()方法啟動(dòng)線程,到run()方法執(zhí)行完畢或遇到未處理異常而中斷 這段時(shí)間內(nèi),線程是激活的

Thread.is_alive()
Thread.isAlive()

Thread.join([timeout]) 調(diào)用Thread.join將會(huì)使主調(diào)線程堵塞,直到被調(diào)用線程運(yùn)行結(jié)束或超時(shí)。參數(shù)timeout是一個(gè)數(shù)值類型,表示超時(shí)時(shí)間,如果未提供該參數(shù),那么主調(diào)線程將一直堵塞到被調(diào)線程結(jié)束

Python GIL(Global Interpreter Lock)
GIL并不是Python的特性,它是在實(shí)現(xiàn)Python解析器(CPython)時(shí)所引入的一個(gè)概念。就好比C++是一套語言(語法)標(biāo)準(zhǔn),但是可以用不同的編譯器來編譯成可執(zhí)行代碼。有名的編譯器例如GCC,INTEL C++,Visual C++等。Python也一樣,同樣一段代碼可以通過CPython,PyPy,Psyco等不同的Python執(zhí)行環(huán)境來執(zhí)行。像其中的JPython就沒有GIL。然而因?yàn)镃Python是大部分環(huán)境下默認(rèn)的Python執(zhí)行環(huán)境。所以在很多人的概念里CPython就是Python,也就想當(dāng)然的把GIL歸結(jié)為Python語言的缺陷。所以這里要先明確一點(diǎn):GIL并不是Python的特性,Python完全可以不依賴于GIL。

線程鎖的使用:

# 鎖:GIL 全局解釋器 它是為了保證線程在運(yùn)行過程中不被搶占
number = 0
lock = threading.RLock()    # 創(chuàng)建鎖


def run(num):
    lock.acquire()  # 加鎖
    global number
    number += 1
    print(number)
    time.sleep(2)
    lock.release()  # 釋放鎖

for i in range(10):
    t = threading.Thread(target=run, args=(i, ))
    t.start()
Join & Daemon

主線程A中,創(chuàng)建了子線程B,并且在主線程A中調(diào)用了B.setDaemon(),這個(gè)的意思是,把主線程A設(shè)置為守護(hù)線程,這時(shí)候,要是主線程A執(zhí)行結(jié)束了,就不管子線程B是否完成,一并和主線程A退出.這就是setDaemon方法的含義,這基本和join是相反的。此外,還有個(gè)要特別注意的:必須在start() 方法調(diào)用之前設(shè)置,如果不設(shè)置為守護(hù)線程,程序會(huì)被無限掛起。

class MyThread1(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        print("thread start")
        time.sleep(3)
        print("thread end")

print("main start")
thread1 = MyThread1()
# thread1.setDaemon(True)     # 設(shè)置子線程是否跟隨主線程一起結(jié)束
thread1.start()
time.sleep(1)
print("satrt join")
# thread1.join()    # 使主線程阻塞,直至子線程運(yùn)行完畢再繼續(xù)主線程
print("end join")
def run(n):
    print("[%s]------running----
" % n)
    time.sleep(2)
    print("--done--")


def main():
    for i in range(5):
        t = threading.Thread(target=run, args=[i,])
        t.start()
        # t.join()
        print("starting thread", t.getName())


m = threading.Thread(target=main,args=[])
# m.setDaemon(True)  # 將主線程設(shè)置為Daemon線程,它退出時(shí),其它子線程會(huì)同時(shí)退出,不管是否執(zhí)行完任務(wù)
m.start()
# m.join()    # 使主線程阻塞,直至子線程運(yùn)行完畢再繼續(xù)主線程
print("---main thread done----")
線程鎖(互斥鎖Mutex)

一個(gè)進(jìn)程下可以啟動(dòng)多個(gè)線程,多個(gè)線程共享父進(jìn)程的內(nèi)存空間,也就意味著每個(gè)線程可以訪問同一份數(shù)據(jù),此時(shí),如果2個(gè)線程同時(shí)要修改同一份數(shù)據(jù),會(huì)出現(xiàn)什么狀況?

num = 100  # 設(shè)定一個(gè)共享變量

def subNum():
    global num # 在每個(gè)線程中都獲取這個(gè)全局變量
    print("--get num:", num)
    time.sleep(2)
    num -= 1 # 對此公共變量進(jìn)行-1操作

thread_list = []
for i in range(100):
    t = threading.Thread(target=subNum)
    t.start()
    thread_list.append(t)

for t in thread_list: # 等待所有線程執(zhí)行完畢
    t.join()

print("final num:", num)
# 加鎖版本

def subNum():
    global num  # 在每個(gè)線程中都獲取這個(gè)全局變量
    print("--get num:", num)
    time.sleep(1)
    lock.acquire()  # 修改數(shù)據(jù)前加鎖
    num -= 1  # 對此公共變量進(jìn)行-1操作
    lock.release()  # 修改后釋放


num = 100  # 設(shè)定一個(gè)共享變量
thread_list = []
lock = threading.Lock()  # 生成全局鎖
for i in range(100):
    t = threading.Thread(target=subNum)
    t.start()
    thread_list.append(t)

for t in thread_list:  # 等待所有線程執(zhí)行完畢
    t.join()

print("final num:", num)
Rlock與Lock的區(qū)別:

RLock允許在同一線程中被多次acquire。而Lock卻不允許這種情況。否則會(huì)出現(xiàn)死循環(huán),程序不知道解哪一把鎖。注意:如果使用RLock,那么acquire和release必須成對出現(xiàn),即調(diào)用了n次acquire,必須調(diào)用n次的release才能真正釋放所占用的鎖

Events
Python提供了Event對象用于線程間通信,它是由線程設(shè)置的信號標(biāo)志,如果信號標(biāo)志位真,則其他線程等待直到信號接觸。

Event對象實(shí)現(xiàn)了簡單的線程通信機(jī)制,它提供了設(shè)置信號,清除信號,等待等用于實(shí)現(xiàn)線程間的通信。

event = threading.Event() 創(chuàng)建一個(gè)event

1 設(shè)置信號
event.set()

使用Event的set()方法可以設(shè)置Event對象內(nèi)部的信號標(biāo)志為真。Event對象提供了isSet()方法來判斷其內(nèi)部信號標(biāo)志的狀態(tài)。
當(dāng)使用event對象的set()方法后,isSet()方法返回真

2 清除信號
event.clear()

使用Event對象的clear()方法可以清除Event對象內(nèi)部的信號標(biāo)志,即將其設(shè)為假,當(dāng)使用Event的clear方法后,isSet()方法返回假

3 等待
event.wait()

Event對象wait的方法只有在內(nèi)部信號為真的時(shí)候才會(huì)很快的執(zhí)行并完成返回。當(dāng)Event對象的內(nèi)部信號標(biāo)志位假時(shí),
則wait方法一直等待到其為真時(shí)才返回。也就是說必須set新號標(biāo)志位真

def do(event):
    print("start")
    event.wait()
    print("execute")

event_obj = threading.Event()
for i in range(10):
    t = threading.Thread(target=do, args=(event_obj,))
    t.start()

event_obj.clear()
inp = input("輸入內(nèi)容:")
if inp == "true":
    event_obj.set()

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/41637.html

相關(guān)文章

  • python模塊之threading

    摘要:的類行為是的類行為的子集,目前尚不支持優(yōu)先級線程組,線程無法銷毀停止暫?;謴?fù)或中斷。表示繼承創(chuàng)建該線程的當(dāng)前線程的屬性。重入鎖,同步原語的一種,可由同一線程多次獲取已持有的鎖。 threading在低級的_thread模塊上構(gòu)建了更高級的線程接口。 threading模塊基于Java線程模型設(shè)計(jì)。不過Java中鎖和條件變量是每個(gè)對象的基本行為,在python中卻是單獨(dú)的對象。pytho...

    nanchen2251 評論0 收藏0
  • python并發(fā)4:使用thread處理并發(fā)

    摘要:如果某線程并未使用很多操作,它會(huì)在自己的時(shí)間片內(nèi)一直占用處理器和。在中使用線程在和等大多數(shù)類系統(tǒng)上運(yùn)行時(shí),支持多線程編程。守護(hù)線程另一個(gè)避免使用模塊的原因是,它不支持守護(hù)線程。 這一篇是Python并發(fā)的第四篇,主要介紹進(jìn)程和線程的定義,Python線程和全局解釋器鎖以及Python如何使用thread模塊處理并發(fā) 引言&動(dòng)機(jī) 考慮一下這個(gè)場景,我們有10000條數(shù)據(jù)需要處理,處理每條...

    joywek 評論0 收藏0
  • # Python 線程

    摘要:多線程和鎖作者博客進(jìn)程和線程進(jìn)程是執(zhí)行中的計(jì)算機(jī)程序。線程包括開始執(zhí)行順序和結(jié)束三部分。的多進(jìn)程相關(guān)模塊模塊是高級別的多線程模塊。線程鎖當(dāng)多線程爭奪鎖時(shí),允許第一個(gè)獲得鎖的線程進(jìn)入臨街區(qū),并執(zhí)行代碼。 Python 多線程和鎖 作者博客:http://zzir.cn/ 進(jìn)程和線程 進(jìn)程是執(zhí)行中的計(jì)算機(jī)程序。每個(gè)進(jìn)程都擁有自己的地址空間、內(nèi)存、數(shù)據(jù)棧及其它的輔助數(shù)據(jù)。操作系統(tǒng)管理著所有的...

    cpupro 評論0 收藏0
  • python并發(fā)編程思考

    摘要:我們以請求網(wǎng)絡(luò)服務(wù)為例,來實(shí)際測試一下加入多線程之后的效果。所以,執(zhí)行密集型操作時(shí),多線程是有用的,對于密集型操作,則每次只能使用一個(gè)線程。說到這里,對于密集型,可以使用多線程或者多進(jìn)程來提高效率。 為了提高系統(tǒng)密集型運(yùn)算的效率,我們常常會(huì)使用到多個(gè)進(jìn)程或者是多個(gè)線程,python中的Threading包實(shí)現(xiàn)了線程,multiprocessing 包則實(shí)現(xiàn)了多進(jìn)程。而在3.2版本的py...

    sshe 評論0 收藏0
  • 談?wù)?em>Python協(xié)程技術(shù)演進(jìn)

    摘要:事件循環(huán)是異步編程的底層基石。對事件集合進(jìn)行輪詢,調(diào)用回調(diào)函數(shù)等一輪事件循環(huán)結(jié)束,循環(huán)往復(fù)。協(xié)程直接利用代碼的執(zhí)行位置來表示狀態(tài),而回調(diào)則是維護(hù)了一堆數(shù)據(jù)結(jié)構(gòu)來處理狀態(tài)。時(shí)代的協(xié)程技術(shù)主要是,另一個(gè)比較小眾。 Coding Crush Python開發(fā)工程師 主要負(fù)責(zé)豈安科技業(yè)務(wù)風(fēng)險(xiǎn)情報(bào)系統(tǒng)redq。 引言 1.1. 存儲(chǔ)器山 存儲(chǔ)器山是 Randal Bryant 在《深入...

    zhiwei 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<