ความปลอดภัยของเธรดในพจนานุกรมของ Python


107

ฉันมีชั้นเรียนที่มีพจนานุกรม

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

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

และฉันทำงาน 4 กระทู้ (หนึ่งสำหรับแต่ละร้านอาหาร) OrderBook.addOrderที่เรียกวิธี นี่คือฟังก์ชั่นที่รันโดยแต่ละเธรด:

def addOrders(restaurant_name):

    #creates orders
    ...

    OrderBook.addOrder(restaurant_name, orders)

มีความปลอดภัยนี้หรือฉันจะต้องใช้ล็อคก่อนที่จะเรียกaddOrder?


2
จะมีปัญหาได้อย่างไรเมื่อแต่ละเธรดเขียนไปยังคีย์อื่น
Jochen Ritzel

65
@ โจเชน: ขึ้นอยู่กับวิธีการใช้งานคำสั่งหลายอย่างอาจผิดพลาด นี่เป็นคำถามที่สมเหตุสมผลมาก
Ned Batchelder

คำตอบ:


97

โครงสร้างในตัวของ Python ปลอดภัยต่อเธรดสำหรับการดำเนินการเดียว แต่บางครั้งอาจเป็นเรื่องยากที่จะเห็นว่าคำสั่งกลายเป็นการดำเนินการหลายอย่าง

รหัสของคุณควรปลอดภัย ข้อควรจำ: การล็อคที่นี่จะไม่เพิ่มค่าใช้จ่ายใด ๆ เลยและจะทำให้คุณสบายใจ

http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm มีรายละเอียดเพิ่มเติม


6
นี่คือ effbot.org เหตุใด / วิธีการติดตั้งระบบล็อค
เตาไฟฟ้า

1
ควรพิจารณาดำเนินการเดียวกับการดำเนินงานคอมโพสิตเช่นได้รับเพิ่มชุด
andy

5
ปัญหาคือเมื่อฉันอ่าน / เขียนคำสั่งนั้นบ่อยๆความสบายใจนั้นจะทำให้ฉันเสียค่าใช้จ่ายมาก
Shihab Shahriar Khan

2
"ล็อคที่นี่จะไม่เพิ่มค่าใช้จ่ายเกือบทั้งหมด": ทำไมถึงเป็นเช่นนั้น?
สูงสุด

32

ใช่ประเภทในตัวเป็นเธรดที่ปลอดภัยโดยเนื้อแท้: http://docs.python.org/glossary.html#term-global-interpreter-lock

สิ่งนี้ช่วยลดความยุ่งยากในการใช้งาน CPython โดยการสร้างโมเดลอ็อบเจ็กต์ ( รวมถึงชนิดบิวท์อินที่สำคัญเช่น dict ) โดยปริยายปลอดภัยจากการเข้าถึงพร้อมกัน


25
นี้ไม่ได้เป็นคุณลักษณะของงูใหญ่ แต่ของCPython
phihag

8
จริง แต่อย่างที่ฉันเข้าใจในตัวใน Jython และ IronPython ยังปลอดภัยต่อเธรดแม้ว่าจะไม่มีการใช้ GIL ก็ตาม (และกลืนที่ไม่ได้บรรทุกมันควรจะโผล่ออกมาและเสนอให้กำจัด GIL ด้วยเช่นกัน) ฉันสันนิษฐานว่าเนื่องจากเขาไม่ได้ระบุล่ามที่เขาใช้นั่นหมายความว่าใน CPython

1
ถูกต้องกรณี Jython: jython.org/jythonbook/en/1.0/…
Evgeni Sergeev

9

คำแนะนำเกี่ยวกับสไตล์ของ Google แนะนำว่าอย่าพึ่งการปรมาณูแบบเผด็จการ

อธิบายรายละเอียดเพิ่มเติมได้ที่: Python variable assignment atomic หรือไม่?

อย่าพึ่งพาความเป็นอะตอมของชนิดในตัว

แม้ว่าประเภทข้อมูลในตัวของ Python เช่นพจนานุกรมดูเหมือนจะมีการดำเนินการเกี่ยวกับอะตอม แต่ก็มีบางกรณีที่ไม่เป็นอะตอม (เช่นถ้า__hash__หรือ__eq__นำไปใช้เป็นวิธีการของ Python) และไม่ควรพึ่งพาความเป็นอะตอม คุณไม่ควรพึ่งพาการกำหนดตัวแปรอะตอม (เนื่องจากสิ่งนี้ขึ้นอยู่กับพจนานุกรม)

ใช้Queueชนิดข้อมูล Queue ของโมดูลเป็นวิธีที่ต้องการในการสื่อสารข้อมูลระหว่างเธรด มิฉะนั้นให้ใช้โมดูลเธรดและแบบดั้งเดิมในการล็อค เรียนรู้เกี่ยวกับการใช้ตัวแปรเงื่อนไขอย่างเหมาะสมเพื่อให้คุณสามารถใช้threading.Conditionแทนการใช้การล็อกระดับล่างได้

และฉันเห็นด้วยกับสิ่งนี้: มี GIL ใน CPython อยู่แล้วดังนั้นประสิทธิภาพที่ได้รับจากการใช้ Lock จะน้อยมาก ค่าใช้จ่ายที่มากขึ้นคือชั่วโมงที่ใช้ในการล่าบั๊กในโค้ดเบสที่ซับซ้อนเมื่อรายละเอียดการใช้งาน CPython เปลี่ยนไปในวันหนึ่ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.