Keamanan Benang dalam kamus Python

105

Saya memiliki kelas yang memegang kamus

class OrderBook:
    orders = {'Restaurant1': None,
              'Restaurant2': None,
              'Restaurant3': None,
              'Restaurant4': None}

    @staticmethod
    def addOrder(restaurant_name, orders):
        OrderBook.orders[restaurant_name] = orders

Dan saya menjalankan 4 utas (satu untuk setiap restoran) yang memanggil metode tersebut OrderBook.addOrder . Berikut adalah fungsi yang dijalankan oleh setiap utas:

def addOrders(restaurant_name):

    #creates orders
    ...

    OrderBook.addOrder(restaurant_name, orders)

Apakah ini aman, atau apakah saya harus menggunakan kunci sebelum menelepon addOrder?

nmat
sumber
2
bagaimana bisa ada masalah ketika setiap utas menulis ke kunci yang berbeda pula.
Jochen Ritzel
64
@Jochen: tergantung bagaimana dicts diimplementasikan, banyak hal yang bisa salah. Ini pertanyaan yang sangat masuk akal.
Ned Batchelder

Jawaban:

95

Struktur built-in Python aman untuk thread untuk operasi tunggal, tetapi terkadang sulit untuk melihat di mana sebuah pernyataan benar-benar menjadi beberapa operasi.

Kode Anda harus aman. Perlu diingat: kunci di sini hampir tidak akan menambah biaya overhead, dan akan memberi Anda ketenangan pikiran.

http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm memiliki detail lebih lanjut.

Ned Batchelder
sumber
6
Berikut ini alasan mengapa-untuk / bagaimana effbot.org menerapkan kunci
kompor
1
Harus mempertimbangkan operasi tunggal vs. operasi gabungan, seperti get-add-set .
andy
5
Masalahnya, ketika saya sering membaca / menulis perintah itu, ketenangan pikiran itu akan merugikan saya.
Shihab Shahriar Khan
2
"kunci di sini hampir tidak menambah overhead": mengapa demikian?
maks
32

Ya, tipe bawaan pada dasarnya aman untuk thread: http://docs.python.org/glossary.html#term-global-interpreter-lock

Ini menyederhanakan implementasi CPython dengan membuat model objek ( termasuk tipe built-in penting seperti dict ) secara implisit aman dari akses bersamaan.


sumber
25
Ini bukan fitur Python, tapi cpython .
phihag
8
Benar, tapi seperti yang saya pahami, built-in di Jython dan IronPython juga aman untuk thread bahkan tanpa menggunakan GIL (dan walet tanpa muatan, jika muncul, mengusulkan untuk menyingkirkan GIL juga). Saya berasumsi bahwa karena dia tidak menyebutkan penerjemah yang dia gunakan, yang dia maksud dalam CPython.
1
Benar dalam kasus Jython: jython.org/jythonbook/en/1.0/…
Evgeni Sergeev
9

Panduan gaya Google menyarankan agar tidak mengandalkan dict atomicity

Dijelaskan lebih rinci di: Apakah tugas variabel Python atom?

Jangan mengandalkan atomicity tipe bawaan.

Sementara tipe data bawaan Python seperti kamus tampaknya memiliki operasi atomik, ada kasus sudut di mana mereka tidak atom (misalnya jika __hash__atau __eq__diimplementasikan sebagai metode Python) dan atomisitasnya tidak boleh diandalkan. Anda juga tidak harus mengandalkan tugas variabel atom (karena ini pada gilirannya bergantung pada kamus).

Gunakan Queuetipe data Antrian modul sebagai cara yang disukai untuk mengkomunikasikan data antar utas. Jika tidak, gunakan modul threading dan primitif pengunciannya. Pelajari tentang penggunaan variabel kondisi yang tepat sehingga Anda dapat menggunakan threading.Conditiondaripada menggunakan kunci tingkat yang lebih rendah.

Dan saya setuju dengan yang ini: sudah ada GIL di CPython, jadi kinerja hit menggunakan Lock akan diabaikan. Jauh lebih mahal adalah waktu yang dihabiskan untuk berburu bug dalam basis kode yang kompleks ketika detail implementasi CPython berubah suatu hari.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber