หากต้องการใช้การเปรียบเทียบ: วัตถุก็เหมือนกับบ้านหลังใหญ่ ประตูเปิดอยู่เสมอ ในบ้านมีห้องหลายห้อง (หรือที่เรียกว่าวิธีการ) ห้องเหล่านี้ถูกล็อค (วิธีซิงโครไนซ์) หรือปลดล็อค (วิธีปกติ) มีกุญแจอยู่ที่ประตูห้อง กุญแจนี้สามารถเปิดห้องที่ล็อคไว้ทั้งหมดได้ นอกจากนี้ ฉันเปรียบเทียบเธรดทั้งหมดที่ต้องการเรียกใช้วิธีการของวัตถุนี้กับผู้ที่ต้องการเข้าห้องใดห้องหนึ่งในบ้านหลังนี้ นั่นคือทั้งหมด เรามาดูกันว่าสิ่งเหล่านี้ทำงานร่วมกันอย่างไร
ที่นี่เราจะชี้แจงข้อกำหนดเบื้องต้นของเราก่อน วัตถุมีวิธีการซิงโครไนซ์อย่างน้อยหนึ่งวิธี มิฉะนั้น คีย์นี้ไม่มีความหมาย แน่นอนว่าจะไม่มีธีมของเราเช่นนี้
มีคนอยากเข้าห้องที่ล็อคไว้ เขาเดินไปที่ประตูบ้านแล้วเห็นกุญแจอยู่ตรงนั้น (แสดงว่ายังไม่มีใครอยากใช้ห้องที่ล็อคอยู่) เขาจึงขึ้นไปหยิบกุญแจและใช้ห้องต่างๆ ตามที่วางแผนไว้ โปรดทราบว่าเขาจะคืนกุญแจทันทีหลังจากใช้ห้องที่ล็อกทุกครั้ง แม้ว่าเขาต้องการใช้ห้องที่ล็อคไว้สองห้องติดต่อกัน เขาก็ต้องคืนกุญแจและนำมันกลับมาระหว่างนั้น
ดังนั้นหลักการของการใช้กุญแจในสถานการณ์ปกติคือ: "ยืมมันเมื่อคุณใช้งานและส่งคืนทันทีที่คุณใช้มัน"
ในขณะนี้ บุคคลอื่นสามารถใช้ห้องที่ปลดล็อคได้โดยไม่มีข้อจำกัด คนหนึ่งสามารถใช้ห้องเดียว หรือสองคนสามารถใช้ห้องเดียวได้ แต่ถ้าใครอยากเข้าห้องที่ล็อคไว้ก็ต้องวิ่งไปที่ประตูแล้วมองดู ถ้าคุณมีกุญแจก็เอาออกไปได้เลย หากไม่มีกุญแจก็ทำได้แค่รอเท่านั้น
หากหลายคนรอกุญแจอยู่ใครจะได้ก่อนเมื่อคืนกุญแจ? ไม่รับประกัน. เช่นเดียวกับผู้ชายในตัวอย่างที่แล้วที่ต้องการใช้ห้องที่ล็อคไว้สองห้องติดต่อกันหากมีคนอื่นรอกุญแจเมื่อเขาคืนกุญแจก็ไม่รับประกันว่าผู้ชายคนนี้จะได้อีกครั้ง (ข้อกำหนด JAVA ระบุไว้อย่างชัดเจนในหลาย ๆ ที่ว่าไม่มีการรับประกัน เช่น จะใช้เวลานานเท่าใดเพื่อให้ Thread.sleep() กลับมาทำงานหลังจากพัก เธรดใดที่มีลำดับความสำคัญเท่ากันจะถูกดำเนินการก่อน และเมื่อใด ล็อคเพื่อเข้าถึงอ็อบเจ็กต์ถูกปล่อยออกมา เธรดหลายตัวในกลุ่มรอจะถูกปล่อยออกมา เธรดใดจะได้รับมันก่อน ฯลฯ ฉันคิดว่าการตัดสินใจขั้นสุดท้ายขึ้นอยู่กับ JVM เหตุผลที่ไม่มีการรับประกันก็เพราะว่าเมื่อ JVM ตัดสินใจข้างต้นก็ไม่ได้ตัดสินเพียงตามเงื่อนไขเดียว แต่มีหลายเงื่อนไขเช่นกัน เงื่อนไขการตัดสินหลายประการหากพูดออกไปอาจส่งผลต่อ JAVA การส่งเสริมการขายอาจเนื่องมาจากการคุ้มครองทรัพย์สินทางปัญญา SUN ไม่ได้ให้การรับประกันและเป็นที่เข้าใจได้ แต่ฉันเชื่อว่าความไม่แน่นอนเหล่านี้ไม่ได้มีความแน่นอนทั้งหมดเพราะจริงๆ แล้วคอมพิวเตอร์เองก็ทำงานตามคำแนะนำ มีกฎเกณฑ์ให้ค้นหา ใครก็ตามที่เคยศึกษาคอมพิวเตอร์จะรู้ดีว่าชื่อทางวิทยาศาสตร์ของตัวเลขสุ่มในคอมพิวเตอร์นั้นเป็นตัวเลขสุ่มหลอกซึ่งเขียนโดยคนใช้วิธีใดวิธีหนึ่ง นอกจากนี้ อาจเป็นเพราะพวกเขาอยากเป็นเช่นกัน แน่นอน มันเป็นเรื่องยุ่งยากมากและไม่สมเหตุสมผล ดังนั้นหากคุณไม่แน่ใจก็อย่ามั่นใจ)
มาดูบล็อกโค้ดที่ซิงโครไนซ์กันอีกครั้ง มันแตกต่างจากวิธีการซิงโครไนซ์เล็กน้อย
1. ในแง่ของขนาด บล็อกโค้ดที่ซิงโครไนซ์มีขนาดเล็กกว่าวิธีการซิงโครไนซ์ คุณสามารถนึกถึงบล็อกโค้ดที่ซิงโครไนซ์เป็นพื้นที่ในห้องที่ปลดล็อกซึ่งคั่นด้วยหน้าจอที่ล็อก
2. บล็อกรหัสการซิงโครไนซ์ยังสามารถระบุคีย์ของออบเจ็กต์อื่นได้ด้วยตนเอง เหมือนกับการระบุว่าจะใช้กุญแจใดในการเปิดล็อคของหน้าจอนี้ได้ คุณสามารถใช้กุญแจของบ้านหลังนี้หรือจะระบุกุญแจของบ้านอื่นเพื่อเปิดก็ได้ ในกรณีนี้ คุณต้องวิ่งไปบ้านอื่น เพื่อเปิดล็อค รับกุญแจนั้นแล้วใช้กุญแจบ้านนั้นเปิดหน้าจอล็อคของบ้านหลังนี้
โปรดจำไว้ว่ากุญแจบ้านอื่นที่คุณได้รับไม่ได้ป้องกันไม่ให้ผู้อื่นเข้าไปในห้องที่ปลดล็อคในบ้านนั้น
เหตุใดจึงต้องใช้บล็อกโค้ดที่ซิงโครไนซ์ ฉันคิดว่ามันควรจะเป็นเช่นนี้: ก่อนอื่น ส่วนการซิงโครไนซ์ของโปรแกรมจะส่งผลต่อประสิทธิภาพการทำงาน และโดยปกติแล้ววิธีการจะสร้างตัวแปรท้องถิ่นบางตัวก่อน จากนั้นจึงดำเนินการบางอย่างกับตัวแปรเหล่านี้ เช่น การคำนวณ การแสดงผล ฯลฯ และการซิงโครไนซ์ครอบคลุม ยิ่งมีโค้ดมากเท่าใด ผลกระทบต่อประสิทธิภาพก็จะยิ่งรุนแรงมากขึ้นเท่านั้น ดังนั้นเราจึงพยายามรักษาขอบเขตของผลกระทบให้น้อยที่สุดเท่าที่จะเป็นไปได้ ทำอย่างไร? บล็อกโค้ดที่ซิงโครไนซ์ เราซิงโครไนซ์เฉพาะส่วนของวิธีการที่ควรซิงโครไนซ์ เช่น การดำเนินการ
นอกจากนี้ บล็อกโค้ดการซิงโครไนซ์สามารถระบุคีย์ได้ คุณลักษณะนี้มีประโยชน์เพิ่มเติมในการครอบครองคีย์ของออบเจ็กต์ภายในระยะเวลาหนึ่ง จำสิ่งที่ฉันพูดไว้ก่อนหน้านี้เกี่ยวกับหลักการใช้กุญแจในสถานการณ์ปกติ นี่ไม่ใช่สถานการณ์ปกติ คีย์ที่คุณได้รับจะไม่ถูกส่งคืนตลอดไป แต่จะส่งคืนเมื่อคุณออกจากบล็อคโค้ดที่ซิงโครไนซ์เท่านั้น
ลองใช้การเปรียบเทียบของผู้ชายก่อนหน้านี้ที่ต้องการใช้ห้องที่ถูกล็อคสองห้องติดต่อกัน ฉันจะใช้ห้องอื่นต่อไปหลังจากใช้ห้องหนึ่งได้อย่างไร? ใช้บล็อคโค้ดที่ซิงโครไนซ์ ขั้นแรกให้สร้างเธรดอื่น สร้างบล็อคโค้ดการซิงโครไนซ์ และชี้ล็อคของบล็อคโค้ดนั้นไปที่กุญแจของบ้าน จากนั้นเริ่มหัวข้อนั้น ตราบใดที่คุณสามารถคว้ากุญแจบ้านได้เมื่อคุณเข้าไปในบล็อครหัสนั้น คุณสามารถเก็บมันไว้จนกว่าคุณจะออกจากบล็อครหัสนั้น กล่าวอีกนัยหนึ่ง คุณสามารถสำรวจห้องที่ถูกล็อคทั้งหมดในห้องนี้ และแม้แต่นอนหลับ (10*60*1,000) แต่ยังมีเส้นด้ายอีก 1,000 เส้นรอกุญแจอยู่ที่ประตู มันค่อนข้างสนุก
เรามาพูดถึงความสัมพันธ์ระหว่างเมธอด sleep() กับคีย์กันดีกว่า หากเธรดถูกบังคับให้เข้าสู่โหมดสลีป() หลังจากได้รับคีย์และเนื้อหาการซิงโครไนซ์ยังไม่เสร็จสิ้น คีย์จะยังคงอยู่ตรงนั้น คีย์จะไม่ถูกส่งกลับจนกว่าจะรันอีกครั้งและเนื้อหาการซิงโครไนซ์ทั้งหมดเสร็จสมบูรณ์ จำไว้ว่าผู้ชายเพิ่งเหนื่อยจากการทำงานและไปพักผ่อน เขายังทำสิ่งที่อยากทำไม่เสร็จ เพื่อป้องกันไม่ให้ผู้อื่นเข้าไปในห้องและทำให้ยุ่งวุ่นวายภายใน เขาต้องสวมกุญแจเพียงดอกเดียวบนร่างกายของเขาแม้ในขณะนอนหลับ
สุดท้ายนี้อาจมีคนถามว่าทำไมเราต้องใช้กุญแจเพียงดอกเดียวในการเปิดประตูแต่ละบาน แทนที่จะใช้กุญแจเพียงดอกเดียวสำหรับประตูแต่ละบาน? ฉันคิดว่านี่เป็นเรื่องของความซับซ้อนอย่างแท้จริง กุญแจดอกเดียวสำหรับประตูเดียวนั้นปลอดภัยกว่าอย่างแน่นอน แต่มันจะเกี่ยวข้องกับปัญหามากมาย การสร้าง การจัดเก็บ การได้มา การคืนกุญแจ ฯลฯ ความซับซ้อนอาจเพิ่มขึ้นในเชิงเรขาคณิตเมื่อจำนวนวิธีการซิงโครไนซ์เพิ่มขึ้น ซึ่งส่งผลกระทบร้ายแรงต่อประสิทธิภาพ นี่ถือได้ว่าเป็นเรื่องของการแลกเปลี่ยน การลดประสิทธิภาพลงอย่างมากเพื่อเพิ่มความปลอดภัยเล็กน้อยเป็นสิ่งที่ไม่พึงประสงค์เพียงใด