การล็อคแบบบล็อคเทียบกับการล็อคแบบไม่บล็อค

ฉันกำลังคิดอยู่ที่นี่: หากคุณมี 2 เธรดที่ดำเนินการการดำเนินการ FAST ที่จำเป็นต้องซิงโครไนซ์ วิธีการไม่บล็อกจะเร็วกว่า/ดีกว่าวิธีการบล็อก/สลับบริบทไม่ใช่หรือ

การไม่บล็อกฉันหมายถึงบางสิ่งเช่น:

ในขณะที่ (จริง) { ถ้า (checkAndGetTheLock ()) พัง; }

สิ่งเดียวที่ฉันคิดได้คือความอดอยาก (โดยที่ CPU หมดแรง) หากคุณมีเธรดมากเกินไปวนรอบล็อค

ฉันจะสร้างสมดุลระหว่างแนวทางหนึ่งกับอีกแนวทางหนึ่งได้อย่างไร


person chrisapotek    schedule 27.02.2012    source แหล่งที่มา
comment
คุณจะดำเนินการล็อคกี่ครั้งต่อ CPU คอร์ต่อวินาที   -  person usr    schedule 27.02.2012
comment
AFAIK, JVM ทำการเพิ่มประสิทธิภาพนี้ให้กับคุณหากไม่มีความขัดแย้งในการล็อค (ซึ่งควรเป็นกรณีนี้หากการดำเนินการรวดเร็ว)   -  person JB Nizet    schedule 27.02.2012
comment
@JB Nizet: ฉันคิดว่าคุณต้องตัดสินใจด้วยตัวเองโดยใช้การซิงโครไนซ์กับ ReentrantLock   -  person chrisapotek    schedule 27.02.2012


คำตอบ (2)


นี่คือสิ่งที่ Java Concurrency ในทางปฏิบัติ พูดเกี่ยวกับหัวข้อนี้:

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

และ (ซึ่งก็คือ IMO ซึ่งเป็นจุดที่สำคัญที่สุด):

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

person JB Nizet    schedule 27.02.2012
comment
ฉันไม่เชื่อว่า JVM บางตัวจะเลือกระหว่างทั้งสองแบบที่ปรับเปลี่ยนได้โดยอิงตามข้อมูลโปรไฟล์ของเวลารอที่ผ่านมา แต่ส่วนใหญ่จะระงับเธรดที่รอการล็อคเท่านั้น แต่คุณไม่สามารถรู้ได้เลยว่า JVM ฮอตสปอตสมัยใหม่เหล่านั้นมีความสามารถอะไร ฉันคิดว่าการซิงโครไนซ์กำลังบล็อกอยู่และ ReentrantLock กำลังรอไม่ว่าง แต่ถ้าพวกเขาสามารถแปลงร่างกันตอนรันไทม์ได้ฉันก็ไม่แน่ใจ - person chrisapotek; 27.02.2012
comment
คุณอ่านเจอที่ไหนว่า ReentrantLock กำลังยุ่งกับการรอคอย? หากเป็นเช่นนั้น มันจะทำให้ JVM ต้องคุกเข่าลงเพื่อรอเป็นเวลานาน javadoc พูดว่า: การล็อกการแยกออกร่วมกันของผู้กลับเข้ามาใหม่ ล็อกด้วยการทำงานพื้นฐานและความหมายเหมือนกับการล็อกมอนิเตอร์โดยนัยที่เข้าถึงได้โดยใช้วิธีการและคำสั่งที่ซิงโครไนซ์ แต่มีความสามารถเพิ่มเติม - person JB Nizet; 27.02.2012
comment
ฉันผิดได้ แต่โดยการเรียกดูซอร์สโค้ด ฉันคิดว่ามันเป็นแนวทาง: fuseyism.com/classpath/doc/java/util/concurrent/locks/ ไม่นะ! JVM ไม่ได้ใช้ ReentrantLock สำหรับสิ่งต่าง ๆ ภายใน - person chrisapotek; 27.02.2012
comment
@chrisapotek ReentrantLock ถูกสร้างขึ้นโดยใช้ AbstractQueuedSynchronizer เป็นกลไกการซิงโครไนซ์ กล่าวอีกนัยหนึ่ง ReentrantLock ใช้ AbstractQueuedSynchronizer เพื่อระงับและปลุกเธรด แต่ดังที่ JB Nizet กล่าวไว้ ReentrantLock นั้นเป็นโครงสร้างการปิดกั้นอย่างแน่นอน - person John Vint; 28.02.2012
comment
ดังนั้นหากฉันต้องการใช้การล็อกการรอแบบยุ่ง ฉันต้องทำด้วยตัวเองโดยใช้อะตอมดั้งเดิมใช่ไหม - person chrisapotek; 28.02.2012
comment
@chrisapotek ใช่คุณสามารถเขียน Mutex อย่างง่ายโดยใช้ AtomicBoolean while(!flag.compareAndSet(false,true)); จะเป็นการรับการล็อคแบบ busy-spin - person John Vint; 29.02.2012

วิธีเดียวที่จะแน่ใจได้คือทดสอบ เมื่อพูดถึงมัลติเธรดและประสิทธิภาพ คุณไม่สามารถคาดเดาได้

person M Platvoet    schedule 27.02.2012
comment
@usr แล้วทำไมคุณไม่โหวตล่ะ? ฉันถูกล่อลวงอย่างมากให้ลงคะแนนสองครั้ง แต่นั่นจะไม่ยุติธรรมกับ M Platvoet - person Martin James; 27.02.2012
comment
@usr - ในกรณีนี้ ฉันจะเพิ่ม upvote ด้วย เพราะมันเป็นวิธีเดียวที่จะแน่ใจ การทดสอบเป็นสิ่งสำคัญ แต่ก่อนที่นักพัฒนาจะไปถึงขั้นตอนนั้น มีการออกแบบบางอย่างที่จะส่งผลให้เกิดประสิทธิภาพที่ต่ำอย่างแน่นอน ไม่จำเป็นต้องตั้งสมมติฐานใดๆ การไม่ใช้มันเป็นเรื่องของการฝึกอบรม/ประสบการณ์ - person Martin James; 27.02.2012