ทำไมต้องล็อคล่ามทั่วโลก


89

ฟังก์ชัน Global Interpreter Lock ของ Python คืออะไร? ภาษาอื่น ๆ ที่คอมไพล์เป็น bytecode ใช้กลไกที่คล้ายกันหรือไม่?


6
คุณควรถามว่า "มันสำคัญหรือไม่"
ล็อต

2
ฉันเห็นด้วยตอนนี้ฉันถือว่าไม่ใช่ปัญหาแล้วใน 2.6 โมดูลการประมวลผลหลายขั้นตอนถูกเพิ่มเข้ามาเพื่อให้คุณสามารถตั้งโปรแกรมโดยใช้หลายกระบวนการในลักษณะเธรด docs.python.org/library/multiprocessing.html
กุฏ

คำตอบ:


69

โดยทั่วไปสำหรับปัญหาด้านความปลอดภัยของเธรดใด ๆ คุณจะต้องปกป้องโครงสร้างข้อมูลภายในของคุณด้วยการล็อก ซึ่งสามารถทำได้ด้วยความละเอียดระดับต่างๆ

  • คุณสามารถใช้การล็อกแบบละเอียดซึ่งโครงสร้างที่แยกจากกันทุกชิ้นจะมีการล็อกของตัวเอง

  • คุณสามารถใช้การล็อกแบบหยาบโดยที่ล็อคเดียวจะปกป้องทุกอย่าง (แนวทาง GIL)

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

วิธีการที่เป็นเม็ดหยาบนั้นตรงกันข้าม เธรดสองเธรดไม่สามารถทำงานพร้อมกันได้ แต่เธรดแต่ละเธรดจะทำงานได้เร็วขึ้นเนื่องจากไม่ได้ทำบัญชีมากนัก ท้ายที่สุดแล้วมันจะลดลงระหว่างความเร็วเธรดเดียวและความขนาน

มีความพยายามสองสามครั้งที่จะลบ GIL ใน python แต่ค่าใช้จ่ายพิเศษสำหรับเครื่องเธรดเดี่ยวมักมีขนาดใหญ่เกินไป บางกรณีอาจทำงานช้าลงแม้ในเครื่องที่มีโปรเซสเซอร์หลายตัวเนื่องจากปัญหาการล็อก

ภาษาอื่น ๆ ที่คอมไพล์เป็น bytecode ใช้กลไกที่คล้ายกันหรือไม่?

มันแตกต่างกันไปและอาจไม่ถือว่าเป็นคุณสมบัติของภาษามากเท่ากับคุณสมบัติการนำไปใช้งาน ตัวอย่างเช่นมีการใช้งาน Python เช่น Jython และ IronPython ซึ่งใช้วิธีการเธรดของ VM ที่เป็นพื้นฐานแทนที่จะใช้วิธี GIL นอกจากนี้เวอร์ชันถัดไปของ Ruby ดูเหมือนจะมุ่งสู่การแนะนำ GIL


1
คุณสามารถอธิบายสิ่งนี้ได้ไหม: 'สองเธรดไม่สามารถทำงานพร้อมกันได้' เมื่อเร็ว ๆ นี้ฉันเขียนเว็บเซิร์ฟเวอร์ง่ายๆใน Python ด้วยมัลติเธรด สำหรับทุกคำขอใหม่จากไคลเอนต์เซิร์ฟเวอร์จะสร้างเธรดใหม่สำหรับมันและเธรดเหล่านั้นจะดำเนินการต่อไป จึงจะมีหลายเธรดทำงานในเวลาเดียวกันใช่ไหม? หรือว่าฉันเข้าใจผิด?
avi

1
@avi AFAIK python thread ไม่สามารถทำงานพร้อมกันได้ แต่ไม่ได้หมายความว่าเธรดหนึ่งต้องบล็อกอีกเธรด GIL หมายความว่าเธรดเดียวเท่านั้นที่สามารถตีความรหัสไพ ธ อนในครั้งเดียวไม่ได้หมายความว่าการจัดการเธรดและการจัดสรรทรัพยากรจะไม่ทำงาน
Benproductions1

2
^ ดังนั้นในช่วงเวลาใดก็ตามเธรดเดียวเท่านั้นที่จะให้บริการเนื้อหาแก่ลูกค้า ... ดังนั้นจึงไม่มีจุดใดที่จะใช้มัลติเธรดเพื่อปรับปรุงประสิทธิภาพ ขวา?
avi

และแน่นอนว่า Java ถูกคอมไพล์เป็นไบต์โค้ดและช่วยให้สามารถล็อกแบบละเอียดได้
Warren Dew

3
@avi กระบวนการผูก IO เช่นเว็บเซิร์ฟเวอร์ยังคงได้รับจากเธรด Python เธรดตั้งแต่สองเธรดขึ้นไปสามารถทำ IO พร้อมกันได้ พวกเขาไม่สามารถตีความ (CPU) ได้พร้อมกัน
Saish

33

ต่อไปนี้มาจากคู่มืออ้างอิง Python / C API อย่างเป็นทางการ :

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

ดังนั้นกฎจึงมีอยู่เฉพาะเธรดที่ได้รับการล็อกตัวแปลส่วนกลางเท่านั้นที่สามารถทำงานบนวัตถุ Python หรือเรียกฟังก์ชัน Python / C API เพื่อให้รองรับโปรแกรม Python แบบหลายเธรดล่ามจะปล่อยและรับการล็อกเป็นประจำโดยค่าเริ่มต้นคำแนะนำทุกๆ 100 ไบต์โค้ด (สามารถเปลี่ยนแปลงได้ด้วย sys.setcheckinterval ()) นอกจากนี้ล็อกยังถูกปลดล็อกและได้รับการร้องขออีกครั้งสำหรับการดำเนินการ I / O ที่อาจบล็อกเช่นการอ่านหรือเขียนไฟล์เพื่อให้เธรดอื่น ๆ สามารถทำงานได้ในขณะที่เธรดที่ร้องขอ I / O กำลังรอให้การดำเนินการ I / O เสร็จสมบูรณ์

ฉันคิดว่ามันสรุปประเด็นได้ดีทีเดียว


1
ฉันอ่านมันเหมือนกัน แต่ฉันไม่เข้าใจว่าทำไม Python ถึงแตกต่างในแง่นี้พูดว่า java (รึเปล่า)
Federico A.Ramponi

@EliBendersky เธรด Python ถูกนำไปใช้เป็น pthreads และได้รับการจัดการโดย OS ( dabeaz.com/python/UnderstandGIL.pdf ) ในขณะที่เธรด Java เป็นเธรดระดับแอปพลิเคชันที่มีการจัดการการตั้งเวลาโดย JVM
gokul_uf

19

ล็อคล่ามทั่วโลกเป็นล็อคประเภท mutex ขนาดใหญ่ที่ป้องกันตัวนับอ้างอิงจากการถูก hosed หากคุณกำลังเขียนโค้ด python ล้วน ๆ ทั้งหมดนี้จะเกิดขึ้นเบื้องหลัง แต่ถ้าคุณฝัง Python ลงใน C คุณอาจต้องถอด / ปลดล็อคอย่างชัดเจน

กลไกนี้ไม่เกี่ยวข้องกับ Python ที่คอมไพล์เป็น bytecode ไม่จำเป็นสำหรับ Java อันที่จริงมันไม่จำเป็นสำหรับJython (ไพ ธ อนคอมไพล์เป็น jvm)

ดูคำถามนี้ด้วย


4
"กลไกนี้ไม่เกี่ยวข้องกับ Python ที่ถูกคอมไพล์เป็น bytecode": แน่นอนมันเป็นสิ่งประดิษฐ์ของการใช้งาน CPython การใช้งานอื่น ๆ (เช่น Jython ที่คุณกล่าวถึง) สามารถปราศจากข้อ จำกัด นี้ได้โดยอาศัยการใช้งานเธรดที่ปลอดภัย
Eli Bendersky

11

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

เธรด Python แต่ละเธรดมีการทำงานหลายอย่างพร้อมกันโดยตัวล่ามโดยการหมุนล็อคทุก ๆ ครั้ง

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

ระบบอื่น ๆ ที่มีมรดกแบบเธรดเดียวซึ่งพัฒนาต่อมาเป็นระบบมัลลิเธรดมักจะมีกลไกบางอย่างในลักษณะนี้ ตัวอย่างเช่นเคอร์เนล Linux มี "Big Kernel Lock" ตั้งแต่ช่วง SMP แรก ๆ เมื่อเวลาผ่านไปเรื่อย ๆ เนื่องจากประสิทธิภาพการทำงานแบบมัลติเธรดกลายเป็นปัญหาจึงมีแนวโน้มที่จะพยายามแบ่งการล็อกประเภทนี้ออกเป็นชิ้นเล็ก ๆ หรือแทนที่ด้วยอัลกอริธึมและโครงสร้างข้อมูลที่ไม่ต้องล็อกซึ่งเป็นไปได้เพื่อเพิ่มปริมาณงานสูงสุด


+1 สำหรับการกล่าวถึงความจริงที่ว่าการล็อคแบบเม็ดหยาบนั้นถูกใช้มากกว่าที่คนส่วนใหญ่คิดโดยเฉพาะ BKL ที่ถูกลืม (ฉันใช้reiserfs- เหตุผลเดียวที่แท้จริงที่ฉันรู้เกี่ยวกับเรื่องนี้)
new123456

3
Linux มี BKL ตั้งแต่เวอร์ชัน 2.6.39 BKL ถูกลบออกทั้งหมด
avi

5
แน่นอน. โปรดทราบว่าเป็นเวลา ~ 3 ปีหลังจากที่ฉันตอบคำถาม =)
Edward KMETT

7

สำหรับคำถามที่สองของคุณไม่ใช่ภาษาสคริปต์ทั้งหมดที่ใช้สิ่งนี้ แต่จะทำให้มีประสิทธิภาพน้อยลงเท่านั้น ตัวอย่างเช่นเธรดใน Ruby จะเป็นสีเขียวและไม่ใช่แบบเนทีฟ

ใน Python เธรดเป็นแบบเนทีฟและ GIL จะป้องกันไม่ให้ทำงานบนคอร์ที่ต่างกัน

ใน Perl เธรดจะยิ่งแย่ลง พวกเขาเพียงแค่คัดลอกล่ามทั้งหมดและยังห่างไกลจากการใช้งานเหมือนใน Python


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