偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Python系列:多線程(threading)的學習和使用

開發(fā) 前端
在Python中,threading庫提供了一種簡單且方便的方式來實現(xiàn)多線程編程。通過使用線程,可以在程序中并行執(zhí)行多個任務,提高程序的性能和響應性。

哈嘍大家好,我是了不起,今天來給大家介紹關(guān)于Python中的線程,threading庫。

引言

在Python中,threading庫提供了一種簡單且方便的方式來實現(xiàn)多線程編程。通過使用線程,可以在程序中并行執(zhí)行多個任務,提高程序的性能和響應性。

了解線程

線程是程序執(zhí)行的最小單元,是操作系統(tǒng)能夠進行運算調(diào)度的基本單位。與進程不同,線程在同一進程下共享相同的內(nèi)存空間,因此線程之間的通信更加方便。在Python中,threading庫提供了對線程的支持。

創(chuàng)建線程

threading庫是Python中的標準庫,無需下載,我們只需在文件中導入threading庫就可以用了。

創(chuàng)建線程的時候主要有兩種方式,第一種是通過繼承threading.Thread類,第二種則是通過傳遞可調(diào)用對象給threading.Thread的構(gòu)造函數(shù),接下來先講解第一種方式。

1.通過繼承threading.Thread類創(chuàng)建線程

import threading

class MyThread(threading.Thread):
    def __init__(self, name):
        super(MyThread, self).__init__()
        self.name = name

    def run(self):
        print(f"Thread {self.name} is running.")

# 創(chuàng)建線程的實例
thread1 = MyThread(name="Thread 1")
thread2 = MyThread(name="Thread 2")

# 啟動線程
thread1.start()
thread2.start()

# 等待線程執(zhí)行完畢
thread1.join()
thread2.join()

print("Main thread is done.")

第一種方式是最常見的方式,創(chuàng)建線程的時候需要先創(chuàng)建一個類,然后繼承threading.Thread,然后再我們創(chuàng)建的類中自定義一個方法,這里我構(gòu)造的是run方法,在這個方法中我們可以去實現(xiàn)線程需要執(zhí)行的主要邏輯。

然后通過thread1和thread2創(chuàng)建對應的構(gòu)造實例,使用線程中的start()方法去啟動線程,最后在使用join()等到線程執(zhí)行完畢,這樣我們創(chuàng)建了一個基本的多線程,執(zhí)行后結(jié)果如下:

然后我們再來了解第二種創(chuàng)建線程的方式。

2.通過傳遞可調(diào)用對象創(chuàng)建線程

import threading

def my_function(name):
    print(f"Thread {name} is running.")

# 創(chuàng)建線程的實例,傳遞一個可調(diào)用對象和參數(shù)
thread1 = threading.Thread(target=my_function, args=("Thread 1",))
thread2 = threading.Thread(target=my_function, args=("Thread 2",))

# 啟動線程
thread1.start()
thread2.start()

# 等待線程執(zhí)行完畢
thread1.join()
thread2.join()

print("Main thread is done.")

這種方式我們是直接通過傳遞給一個可調(diào)用對象給threading.Thread的構(gòu)造函數(shù),我們所傳遞的這個可執(zhí)行對象可以是函數(shù)、方法、或者是__call__等方法類的實例,

其中在threading.Thread實例中,通過使用target參數(shù)指定我們需要調(diào)用的對象,注意這里指定調(diào)用對象是不需要加括號,直接傳需要調(diào)用的可執(zhí)行對象名就行,后面就和上面一樣,通過使用start()方法和join()方法,執(zhí)行結(jié)果也是跟第一種方式一樣。

以上兩種方式都可以創(chuàng)建線程,選擇那種一般取決于個人在項目中的代碼風格和偏好,但是最終都是需要確保的是,無論使用哪種方式我們都需要保證在調(diào)用的方法中包含有線程的主要邏輯。

線程同步

Python中的線程和其他語言中的線程邏輯也是一樣,如果創(chuàng)建了多個線程,那么這幾個線程就是共享內(nèi)存,可能會導致數(shù)據(jù)競爭和不確定的結(jié)果,所以我們需要在線程中加鎖(lock)。

1.鎖的基本用法

在python中,如果需要對線程加鎖我們就需要用到threading.lock()這個方法:

import threading

# 共享資源
counter = 0

# 創(chuàng)建鎖對象
my_lock = threading.Lock()

def increment_counter():
    global counter
    for _ in range(1000000):
        with my_lock:
            counter += 1

# 創(chuàng)建兩個線程,分別增加計數(shù)器的值
thread1 = threading.Thread(target=increment_counter)
thread2 = threading.Thread(target=increment_counter)

# 啟動線程
thread1.start()
thread2.start()

# 等待兩個線程執(zhí)行完畢
thread1.join()
thread2.join()

print(f"Final counter value: {counter}")

在上述代碼中,我們通過創(chuàng)建了一個全局鎖對象,然后在調(diào)用的可執(zhí)行對象中,使用with語句來獲取鎖和釋放鎖,以此來確保線程共享的資源是原子的。這樣可以避免多個線程對counter的參數(shù)結(jié)果進行數(shù)據(jù)競爭。

從這個簡單的代碼上我們可能看不出執(zhí)行后實際有什么不同,接下來我舉一個例子來說明沒有加鎖和加了鎖后的執(zhí)行結(jié)果。

2.不加鎖執(zhí)行

import threading

class BankAccount:
    def __init__(self, balance):
        self.balance = balance

    def withdraw(self, amount):
        current_balance = self.balance
        new_balance = current_balance - amount
        # 模擬取款操作的延遲
        threading.Event().wait(0.1)
        self.balance = new_balance
        return new_balance

# 創(chuàng)建一個共享的銀行賬戶
account = BankAccount(balance=1000)

def withdraw_from_account(account, amount):
    for _ in range(3):
        new_balance = account.withdraw(amount)
        print(f"Withdraw {amount}, New Balance: {new_balance}")

# 創(chuàng)建兩個線程進行取款操作
thread1 = threading.Thread(target=withdraw_from_account, args=(account, 100))
thread2 = threading.Thread(target=withdraw_from_account, args=(account, 150))

# 啟動兩個線程
thread1.start()
thread2.start()

# 等待兩個線程執(zhí)行完畢
thread1.join()
thread2.join()

print(f"Final Balance: {account.balance}")

執(zhí)行結(jié)果:

在上面這個不加鎖的實例中,我們用withdraw方法來模擬取款操作,然后通過兩個線程來對同時對賬戶進行取款操作,但是由于這個實例中沒有加鎖,就會出現(xiàn)下面的情況:

  • thread1讀取了賬戶余額(假設為1000)。
  • thread2也讀取了相同的賬戶余額(仍然是1000)。
  • thread1執(zhí)行取款操作,更新了賬戶余額為900。
  • thread2執(zhí)行取款操作,更新了賬戶余額為850。

就這樣,本來是同一個賬戶,但是兩個線程都是各管各的,最后導致兩個線程都取了3次錢后,最后得出的結(jié)果是賬戶里面還剩了550元。

接下來我們再看看加鎖后的執(zhí)行結(jié)果:

import threading

class BankAccount:
    def __init__(self, balance):
        self.balance = balance
        self.lock = threading.Lock()

    def withdraw(self, amount):
        with self.lock:
            current_balance = self.balance
            new_balance = current_balance - amount
            # 模擬取款操作的延遲
            threading.Event().wait(0.1)
            self.balance = new_balance
            return new_balance

# 創(chuàng)建一個共享的銀行賬戶
account = BankAccount(balance=1000)

def withdraw_from_account(account, amount):
    for _ in range(3):
        new_balance = account.withdraw(amount)
        print(f"Withdraw {amount}, New Balance: {new_balance}")

# 創(chuàng)建兩個線程進行取款操作
thread1 = threading.Thread(target=withdraw_from_account, args=(account, 100))
thread2 = threading.Thread(target=withdraw_from_account, args=(account, 150))

# 啟動兩個線程
thread1.start()
thread2.start()

# 等待兩個線程執(zhí)行完畢
thread1.join()
thread2.join()

print(f"Final Balance: {account.balance}")

同樣的實例,我們通過在實例中加鎖后再去執(zhí)行,結(jié)果如下:

通過在實例中添加with self.lock后,我們保證了兩個線程訪問余額blance的原子性,不管是有多少個線程,每個線程訪問的余額始終是其他線程取錢后的最新結(jié)果,這樣就保證了代碼程序執(zhí)行后的結(jié)果是正確的。

以上是今天分享的關(guān)于Python中一些基本的線程使用,有興趣的小伙伴想要深入學習threading這個模塊的話可以在留言區(qū)打出threading,人多的話我下期就繼續(xù)更新這個模塊。

責任編輯:趙寧寧 來源: Python都知道
相關(guān)推薦

2021-06-11 06:54:35

PythonThreadingMultiproces

2023-06-13 13:39:00

多線程異步編程

2021-09-11 15:26:23

Java多線程線程池

2023-06-07 13:49:00

多線程編程C#

2023-06-05 07:56:10

線程分配處理器

2023-06-06 08:17:52

多線程編程Thread類

2009-03-12 10:52:43

Java線程多線程

2010-07-26 13:27:19

Perl多線程

2013-06-13 13:19:38

多線程

2009-08-03 11:07:18

Scala Actor

2023-06-09 07:59:37

多線程編程鎖機制

2023-06-12 08:30:08

多線程編程線程調(diào)試

2016-11-10 16:30:22

Java多線程

2023-06-08 08:21:08

多線程編程線程間通信

2020-08-20 07:54:58

Node多線程解密

2009-08-26 18:13:55

C#多線程lock

2024-09-27 19:42:09

工具C#Task?

2024-09-29 16:22:18

多線程TaskC#

2009-06-11 10:48:53

Java多線程

2009-06-11 10:22:18

Java多線程
點贊
收藏

51CTO技術(shù)棧公眾號