Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana untuk menyelesaikan ralat konkurensi yang tidak selamat dalam fungsi Python?

Bagaimana untuk menyelesaikan ralat konkurensi yang tidak selamat dalam fungsi Python?

WBOY
WBOYasal
2023-06-24 12:37:441265semak imbas

Python ialah bahasa pengaturcaraan peringkat tinggi yang popular Ia mempunyai sintaks yang ringkas dan mudah difahami, perpustakaan standard yang kaya dan sokongan komuniti sumber terbuka. Ia juga menyokong pelbagai paradigma pengaturcaraan, seperti pengaturcaraan berorientasikan objek, dll. Khususnya, Python digunakan secara meluas dalam pemprosesan data, pembelajaran mesin, pengkomputeran saintifik dan bidang lain.

Walau bagaimanapun, Python juga mempunyai beberapa masalah dalam pengaturcaraan berbilang benang atau berbilang proses. Salah satunya ialah ketidakamanan bersama. Artikel ini akan memperkenalkan cara menyelesaikan ralat konkurensi yang tidak selamat dalam fungsi Python daripada aspek berikut.

1. Sebab-sebab konkurensi yang tidak selamat

Sebab-sebab konkurensi yang tidak selamat selalunya berkaitan dengan sumber yang dikongsi. Sumber yang dikongsi dalam fungsi boleh menjadi pembolehubah global, atribut kelas, pembolehubah modul, fail, dsb. Jika berbilang urutan atau proses mengakses sumber yang dikongsi pada masa yang sama, ralat yang tidak dapat diramalkan mungkin berlaku. Contohnya, jika berbilang benang mengubah suai pembolehubah global yang sama pada masa yang sama, hasil akhir mungkin tidak seperti yang diharapkan oleh program.

Berikut ialah contoh kod:

import threading

counter = 0

def increment():
    global counter
    for i in range(100000):
        counter += 1

threads = []
for i in range(10):
    t = threading.Thread(target=increment)
    threads.append(t)

for t in threads:
    t.start()

for t in threads:
    t.join()

print("counter:", counter)

Kod di atas mencipta 10 utas, dan setiap utas melaksanakan fungsi kenaikan. Fungsi fungsi ini adalah untuk meningkatkan pembolehubah global counter 100000 kali. Walau bagaimanapun, disebabkan oleh berbilang urutan mengakses pembolehubah counter pada masa yang sama, keadaan serentak yang tidak selamat akan berlaku, menyebabkan keputusan akhir tidak dijangka. increment函数。该函数的作用是将全局变量counter增加100000次。然而,由于多个线程同时访问counter变量,就会出现并发不安全的情况,导致最终的结果并非是预期的。

2.使用互斥锁解决并发不安全的问题

为了解决函数中的并发不安全问题,我们需要使用线程同步技术。其中,互斥锁是一种简单有效的线程同步机制,它可以保证同时只有一个线程可以访问共享资源。当一个线程获取到互斥锁后,其他试图获取该锁的线程就会被阻塞,直到该线程释放锁。

以下是修改后的代码,使用互斥锁解决上述示例中的并发不安全问题:

import threading

counter = 0
lock = threading.Lock()

def increment():
    global counter
    for i in range(100000):
        lock.acquire()
        counter += 1
        lock.release()

threads = []
for i in range(10):
    t = threading.Thread(target=increment)
    threads.append(t)

for t in threads:
    t.start()

for t in threads:
    t.join()

print("counter:", counter)

在上述代码中,我们创建了一个threading.Lock()对象,用于实现互斥锁。在修改全局变量counter时,首先要获取锁,然后再释放锁。这样,就确保了同一时间只有一个线程可以修改全局变量,避免了并发不安全的问题。

3.使用线程安全的数据结构

除了使用互斥锁之外,我们还可以使用线程安全的数据结构来避免并发不安全的问题。Python提供了一些线程安全的数据结构,例如queue.Queuecollections.dequethreading.local等。这些数据结构都是线程安全的,可以在多线程环境下安全地使用。

以下是同样的示例代码,使用Python标准库中的queue.Queue替换全局变量counter,从而实现了线程安全:

import threading
import queue

q = queue.Queue()

def increment():
    for i in range(100000):
        q.put(1)

threads = []
for i in range(10):
    t = threading.Thread(target=increment)
    threads.append(t)

for t in threads:
    t.start()

for t in threads:
    t.join()

print("counter:", q.qsize())

在上述代码中,我们创建了一个queue.Queue()对象,用于存储任务。在每个线程中,我们向队列中放入100000个任务(即数字1)。最后,我们统计队列中任务的数量,就可以得到正确的结果。由于queue.Queue

2. Gunakan kunci mutex untuk menyelesaikan isu konkurensi yang tidak selamat

Untuk menyelesaikan isu konkurensi yang tidak selamat dalam fungsi, kita perlu menggunakan teknologi penyegerakan benang. Antaranya, kunci mutex ialah mekanisme penyegerakan benang yang mudah dan berkesan, yang boleh memastikan bahawa hanya satu utas boleh mengakses sumber yang dikongsi pada masa yang sama. Apabila benang memperoleh kunci mutex, benang lain yang cuba mendapatkan kunci akan disekat sehingga benang melepaskan kunci.

Berikut ialah kod yang diubah suai yang menggunakan kunci mutex untuk menyelesaikan masalah konkurensi yang tidak selamat dalam contoh di atas: 🎜rrreee🎜Dalam kod di atas, kami mencipta objek threading.Lock(), menggunakan To melaksanakan kunci mutex. Apabila mengubah suai pembolehubah global counter, anda mesti memperoleh kunci dahulu dan kemudian melepaskan kunci itu. Dengan cara ini, dipastikan bahawa hanya satu utas boleh mengubah suai pembolehubah global pada masa yang sama, mengelakkan isu konkurensi yang tidak selamat. 🎜🎜3. Gunakan struktur data selamat benang🎜🎜Selain menggunakan kunci mutex, kami juga boleh menggunakan struktur data selamat benang untuk mengelakkan isu konkurensi yang tidak selamat. Python menyediakan beberapa struktur data selamat benang, seperti queue.Queue, collections.deque, threading.local, dsb. Struktur data ini selamat untuk benang dan boleh digunakan dengan selamat dalam persekitaran berbilang benang. 🎜🎜Berikut ialah kod sampel yang sama, menggunakan queue.Queue daripada perpustakaan standard Python untuk menggantikan pembolehubah global counter, sekali gus mencapai keselamatan thread: 🎜rrreee🎜In kod di atas , kami mencipta objek queue.Queue() untuk menyimpan tugasan. Dalam setiap urutan, kami meletakkan 100000 tugasan (iaitu nombor 1) ke dalam baris gilir. Akhirnya, kita boleh mendapatkan hasil yang betul dengan mengira bilangan tugasan dalam baris gilir. Memandangkan queue.Queue selamat untuk benang, berbilang urutan boleh meletakkan tugasan ke dalam baris gilir pada masa yang sama tanpa menyebabkan isu konkurensi yang tidak selamat. 🎜🎜4. Kesimpulan🎜🎜Artikel ini memperkenalkan masalah konkurensi yang tidak selamat dalam fungsi Python, dan cara menggunakan kunci mutex dan struktur data selamat benang untuk menyelesaikan masalah ini. Kunci Mutex ialah mekanisme penyegerakan benang yang mudah dan berkesan yang memastikan bahawa hanya satu utas boleh mengakses sumber yang dikongsi pada masa yang sama struktur data selamat benang selamat digunakan dalam persekitaran berbilang benang. Dalam pengaturcaraan sebenar, kita perlu memberi perhatian kepada cara menggunakan teknologi ini untuk memastikan ketepatan dan kestabilan program. 🎜

Atas ialah kandungan terperinci Bagaimana untuk menyelesaikan ralat konkurensi yang tidak selamat dalam fungsi Python?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn