เมื่อใช้คำหลักภาษา Java เพื่อแก้ไขวิธีการหรือบล็อกโค้ดก็สามารถตรวจสอบให้แน่ใจว่าส่วนใหญ่หนึ่งเธรดจะดำเนินการรหัสในเวลาเดียวกัน
1. เมื่อสองเธรดพร้อมกันเข้าถึงบล็อกรหัสที่ซิงโครไนซ์นี้ (นี้) ซิงโครไนซ์ในวัตถุวัตถุเดียวกันสามารถดำเนินการได้เพียงหนึ่งเธรดภายในหนึ่งครั้ง เธรดอื่นจะต้องรอให้เธรดปัจจุบันเรียกใช้งานบล็อกรหัสนี้ก่อนที่จะสามารถเรียกใช้งานบล็อกรหัส
2. อย่างไรก็ตามเมื่อเธรดหนึ่งเข้าถึงบล็อกรหัสการซิงโครไนซ์ซิงโครไนซ์ (นี้) ของวัตถุเธรดอื่นยังสามารถเข้าถึงบล็อกรหัสซิงโครไนซ์ที่ไม่ซิงโครไนซ์ (นี่) ในวัตถุนั้น
3. เป็นสิ่งสำคัญอย่างยิ่งที่เมื่อเธรดเข้าถึงบล็อกรหัสซิงโครไนซ์ซิงโครไนซ์ (นี้) ของวัตถุเธรดอื่น ๆ จะบล็อกการเข้าถึงไปยังบล็อกรหัสซิงโครไนซ์อื่น ๆ ทั้งหมดที่ซิงโครไนซ์ (นี้) ในวัตถุ
4. ตัวอย่างที่สามยังใช้กับบล็อกรหัสซิงโครนัสอื่น ๆ นั่นคือเมื่อเธรดเข้าถึงบล็อกรหัสซิงโครไนซ์ซิงโครไนซ์ (นี้) ของวัตถุจะได้รับการล็อควัตถุของวัตถุนี้ เป็นผลให้เธรดอื่น ๆ เข้าถึงส่วนรหัสแบบซิงโครนัสทั้งหมดของวัตถุวัตถุถูกบล็อกชั่วคราว
5. กฎข้างต้นใช้กับล็อควัตถุอื่น ๆ
ยกตัวอย่าง:
1. เมื่อสองเธรดพร้อมกันเข้าถึงบล็อกรหัสที่ซิงโครไนซ์นี้ (นี้) ซิงโครไนซ์ในวัตถุวัตถุเดียวกันสามารถดำเนินการได้เพียงหนึ่งเธรดภายในหนึ่งครั้ง เธรดอื่นจะต้องรอให้เธรดปัจจุบันเรียกใช้งานบล็อกรหัสนี้ก่อนที่จะสามารถเรียกใช้งานบล็อกรหัส
แพ็คเกจ ths; คลาสสาธารณะ Thread1 ใช้งาน runnable {public void run () {ซิงโครไนซ์ (นี่) {สำหรับ (int i = 0; i <5; i ++) {system.out.println (thread.currentthread () getName () + "synchronized loop" + i); }}} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {thread1 t1 = thread1 () ใหม่ (); เธรด ta = เธรดใหม่ (t1, "a"); เธรด tb = เธรดใหม่ (T1, "B"); ta.start (); tb.start (); -ผลลัพธ์:
วนวนแบบซิงโครไนซ์ 0
วนวนแบบซิงโครไนซ์ 1
วนซ้ำ 2
วนวนแบบซิงโครไนซ์ 3
วนรอบ 4
B Synchronized Loop 0
B Synchronized Loop 1
B Synchronized Loop 2
B Synchronized Loop 3
B Synchronized Loop 4
2. อย่างไรก็ตามเมื่อเธรดหนึ่งเข้าถึงบล็อกรหัสการซิงโครไนซ์ซิงโครไนซ์ (นี้) ของวัตถุเธรดอื่นยังสามารถเข้าถึงบล็อกรหัสซิงโครไนซ์ที่ไม่ซิงโครไนซ์ (นี่) ในวัตถุนั้น
แพ็คเกจ ths; คลาสสาธารณะ Thread2 {โมฆะสาธารณะ m4t1 () {ซิงโครไนซ์ (นี่) {int i = 5; ในขณะที่ (i--> 0) {system.out.println (thread.currentthread (). getName () + ":" + i); ลอง {thread.sleep (500); } catch (interruptedException IE) {}}}} โมฆะสาธารณะ m4t2 () {int i = 5; ในขณะที่ (i--> 0) {system.out.println (thread.currentthread (). getName () + ":" + i); ลอง {thread.sleep (500); } catch (interruptedException ie) {}}} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {final thread2 myt2 = thread2 (ใหม่); เธรด t1 = เธรดใหม่ (ใหม่ runnable () {public void run () {myt2.m4t1 ();}}, "t1"); เธรด t2 = เธรดใหม่ (ใหม่ runnable () {public void run () {myt2.m4t2 ();}}, "t2"); t1.start (); t2.start (); - ผลลัพธ์:
T1: 4
T2: 4
T1: 3
T2: 3
T1: 2
T2: 2
T1: 1
T2: 1
T1: 0
T2: 0
3. เป็นสิ่งสำคัญอย่างยิ่งที่เมื่อเธรดเข้าถึงบล็อกรหัสซิงโครไนซ์ซิงโครไนซ์ (นี้) ของวัตถุเธรดอื่น ๆ จะบล็อกการเข้าถึงไปยังบล็อกรหัสซิงโครไนซ์อื่น ๆ ทั้งหมดที่ซิงโครไนซ์ (นี้) ในวัตถุ
// แก้ไข Thread2.M4T2 () วิธี: โมฆะสาธารณะ M4T2 () {ซิงโครไนซ์ (นี่) {int i = 5; ในขณะที่ (i--> 0) {system.out.println (thread.currentthread (). getName () + ":" + i); ลอง {thread.sleep (500); } catch (interruptedException ie) {}}}}ผลลัพธ์:
T1: 4
T1: 3
T1: 2
T1: 1
T1: 0
T2: 4
T2: 3
T2: 2
T2: 1
T2: 0
4. ตัวอย่างที่สามยังใช้กับบล็อกรหัสซิงโครนัสอื่น ๆ นั่นคือเมื่อเธรดเข้าถึงบล็อกรหัสซิงโครไนซ์ซิงโครไนซ์ (นี้) ของวัตถุจะได้รับการล็อควัตถุของวัตถุนี้ เป็นผลให้เธรดอื่น ๆ เข้าถึงส่วนรหัสแบบซิงโครนัสทั้งหมดของวัตถุวัตถุถูกบล็อกชั่วคราว
// แก้ไขเมธอด thread2.m4t2 () ดังนี้: โมฆะที่ซิงโครไนซ์สาธารณะ m4t2 () {int i = 5; ในขณะที่ (i--> 0) {system.out.println (thread.currentthread (). getName () + ":" + i); ลอง {thread.sleep (500); } catch (interruptedException IE) {}}} ผลลัพธ์:
T1: 4
T1: 3
T1: 2
T1: 1
T1: 0
T2: 4
T2: 3
T2: 2
T2: 1
T2: 0
5. กฎข้างต้นใช้กับล็อควัตถุอื่น ๆ :
แพ็คเกจ ths; คลาสสาธารณะ Thread3 {คลาสภายใน {โมฆะส่วนตัว m4t1 () {int i = 5; ในขณะที่ (i--> 0) {system.out.println (thread.currentthread (). getName () + ": inner.m4t1 () =" + i); ลอง {thread.sleep (500); } catch (interruptedException IE) {}}} โมฆะส่วนตัว m4t2 () {int i = 5; ในขณะที่ (i--> 0) {system.out.println (thread.currentthread (). getName () + ": inner.m4t2 () =" + i); ลอง {thread.sleep (500); } catch (interruptedException IE) {}}}} โมฆะส่วนตัว M4T1 (ด้านใน) {ซิงโครไนซ์ (ด้านใน) {// ใช้วัตถุล็อควัตถุภายใน M4T1 (); } โมฆะส่วนตัว M4T2 (ด้านใน) {inner.m4t2 (); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {final thread3 myt3 = new Thread3 (); inner inner สุดท้าย = myt3.new inner (); เธรด t1 = เธรดใหม่ (ใหม่ runnable () {public void run () {myt3.m4t1 (inner);}}, "t1"); เธรด t2 = เธรดใหม่ (ใหม่ runnable () {public void run () {myt3.m4t2 (ภายใน);}}, "t2"); t1.start (); t2.start (); -ผลลัพธ์:
แม้ว่าเธรด T1 จะได้รับการล็อควัตถุด้านในเนื่องจากเธรด T2 เข้าถึงส่วนอะซิงโครนัสในด้านในเดียวกัน ดังนั้นทั้งสองเธรดไม่รบกวนกันและกัน
T1: inner.m4t1 () = 4
T2: inner.m4t2 () = 4
T1: inner.m4t1 () = 3
T2: inner.m4t2 () = 3
T1: inner.m4t1 () = 2
T2: inner.m4t2 () = 2
T1: inner.m4t1 () = 1
T2: inner.m4t2 () = 1
T1: inner.m4t1 () = 0
t2: inner.m4t2 () = 0
ตอนนี้ใส่ซิงโครไนซ์ด้านหน้าของ inner.m4t2 ():
โมฆะที่ซิงโครไนซ์ส่วนตัว M4T2 () {int i = 5; ในขณะที่ (i--> 0) {system.out.println (thread.currentthread (). getName () + ": inner.m4t2 () =" + i); ลอง {thread.sleep (500); } catch (interruptedException IE) {}}}ผลลัพธ์:
แม้ว่าเธรด T1 และ T2 จะเข้าถึงสองส่วนที่ไม่เกี่ยวข้องของวัตถุภายในเดียวกันเนื่องจาก T1 ได้รับการล็อควัตถุเป็นครั้งแรกไปยังด้านในการเข้าถึงของ T2 ไปยัง Inner.m4t2 () ยังถูกบล็อกเนื่องจาก M4T2 () เป็นวิธีการซิงโครไนซ์ในด้านใน
T1: inner.m4t1 () = 4
T1: inner.m4t1 () = 3
T1: inner.m4t1 () = 2
T1: inner.m4t1 () = 1
T1: inner.m4t1 () = 0
T2: inner.m4t2 () = 4
T2: inner.m4t2 () = 3
T2: inner.m4t2 () = 2
T2: inner.m4t2 () = 1
t2: inner.m4t2 () = 0
ข้อ 2:
คำหลักที่ซิงโครไนซ์ซึ่งรวมถึงการใช้งานสองวิธี: วิธีที่ซิงโครไนซ์และบล็อกซิงโครไนซ์
1. วิธีการซิงโครไนซ์: ประกาศวิธีการซิงโครไนซ์โดยการเพิ่มคำหลักที่ซิงโครไนซ์ลงในการประกาศวิธีการ ชอบ:
Public Synchronized Void AccessVal (int newVal);
วิธีการที่ซิงโครไนซ์ควบคุมการเข้าถึงตัวแปรสมาชิกคลาส: แต่ละอินสแตนซ์คลาสสอดคล้องกับการล็อคและแต่ละวิธีที่ซิงโครไนซ์จะต้องได้รับการล็อคของอินสแตนซ์คลาสที่เรียกวิธีการก่อนที่จะสามารถดำเนินการได้ มิฉะนั้นเธรดที่เป็นของมันถูกบล็อก เมื่อใช้วิธีการแล้วมันจะครอบครองล็อคเท่านั้น ล็อคจะไม่ถูกปล่อยออกมาจนกว่าจะกลับมาจากวิธีการ เธรดที่ถูกบล็อกสามารถรับการล็อคและป้อนสถานะการทำงานได้อีกครั้ง กลไกนี้ทำให้มั่นใจได้ว่าในเวลาเดียวกันสำหรับแต่ละชั้นเรียนส่วนใหญ่หนึ่งฟังก์ชั่นสมาชิกทั้งหมดที่ประกาศว่าซิงโครไนซ์อยู่ในสถานะปฏิบัติการ (เพราะส่วนใหญ่หนึ่งสามารถรับล็อคที่สอดคล้องกับอินสแตนซ์ของคลาส) ดังนั้นจึงหลีกเลี่ยงการเข้าถึงตัวแปรสมาชิกชั้นเรียน (ตราบใดที่วิธีการทั้งหมดที่เป็นไปได้
ใน Java ไม่เพียง แต่อินสแตนซ์ของคลาสเท่านั้น แต่แต่ละคลาสยังสอดคล้องกับการล็อคดังนั้นเราจึงสามารถประกาศฟังก์ชั่นสมาชิกแบบคงที่ของคลาสที่ซิงโครไนซ์เพื่อควบคุมการเข้าถึงตัวแปรสมาชิกคงที่ของคลาส
ข้อเสียของวิธีการซิงโครไนซ์: การประกาศวิธีการขนาดใหญ่เนื่องจากการซิงโครไนซ์จะส่งผลกระทบอย่างมากต่อประสิทธิภาพ โดยทั่วไปหากวิธีการของคลาสเธรด Run () ถูกประกาศว่าเป็นซิงโครไนซ์เนื่องจากมันทำงานตลอดชีวิตของเธรดมันจะทำให้มันไม่ประสบความสำเร็จในวิธีการซิงโครไนซ์ใด ๆ ของคลาสนี้ แน่นอนว่าเราสามารถแก้ปัญหานี้ได้โดยใส่รหัสที่เข้าถึงตัวแปรสมาชิกชั้นเรียนเป็นวิธีพิเศษประกาศว่ามันเป็นซิงโครไนซ์และเรียกมันในวิธีหลัก แต่ Java ให้วิธีแก้ปัญหาที่ดีกว่านั่นคือบล็อกที่ซิงโครไนซ์
2. บล็อกซิงโครไนซ์: ประกาศบล็อกที่ซิงโครไนซ์ผ่านคำหลักที่ซิงโครไนซ์ ไวยากรณ์มีดังนี้:
ซิงโครไนซ์ (syncobject) {// รหัสที่อนุญาตให้ควบคุมการเข้าถึง} บล็อกที่ซิงโครไนซ์เป็นบล็อกโค้ดที่รหัสจะต้องได้รับการล็อคของวัตถุ syncobject (ดังที่ได้กล่าวไว้ก่อนหน้านี้อาจเป็นอินสแตนซ์คลาสหรือคลาส) ก่อนที่จะสามารถดำเนินการได้ กลไกเฉพาะนั้นเหมือนกับที่อธิบายไว้ข้างต้น เนื่องจากสามารถกำหนดเป้าหมายได้ที่บล็อกรหัสใด ๆ และวัตถุที่ล็อคสามารถระบุได้ตลอดเวลาจึงมีความยืดหยุ่นมากขึ้น
ความเข้าใจบางอย่างเกี่ยวกับการซิงโครไนซ์ (นี่) <br /> 1 เมื่อสองเธรดพร้อมกันเข้าถึงบล็อกรหัสที่ซิงโครไนซ์นี้ (นี้) ซิงโครไนซ์ในวัตถุเดียวกันสามารถดำเนินการเธรดได้เพียงครั้งเดียวภายในหนึ่งครั้ง เธรดอื่นจะต้องรอให้เธรดปัจจุบันเรียกใช้งานบล็อกรหัสนี้ก่อนที่จะสามารถเรียกใช้งานบล็อกรหัส
2. อย่างไรก็ตามเมื่อเธรดหนึ่งเข้าถึงบล็อกรหัสการซิงโครไนซ์ซิงโครไนซ์ (นี้) ของวัตถุเธรดอื่นยังสามารถเข้าถึงบล็อกรหัสซิงโครไนซ์ที่ไม่ซิงโครไนซ์ (นี่) ในวัตถุนั้น
3. เป็นสิ่งสำคัญอย่างยิ่งที่เมื่อเธรดเข้าถึงบล็อกรหัสซิงโครไนซ์ซิงโครไนซ์ (นี้) ของวัตถุเธรดอื่น ๆ จะบล็อกการเข้าถึงไปยังบล็อกรหัสซิงโครไนซ์อื่น ๆ ทั้งหมดที่ซิงโครไนซ์ (นี้) ในวัตถุ
4. ตัวอย่างที่สามยังใช้กับบล็อกรหัสซิงโครนัสอื่น ๆ นั่นคือเมื่อเธรดเข้าถึงบล็อกรหัสซิงโครไนซ์ซิงโครไนซ์ (นี้) ของวัตถุจะได้รับการล็อควัตถุของวัตถุนี้ เป็นผลให้เธรดอื่น ๆ เข้าถึงส่วนรหัสแบบซิงโครนัสทั้งหมดของวัตถุวัตถุถูกบล็อกชั่วคราว
5. กฎข้างต้นใช้กับล็อควัตถุอื่น ๆ
วิธีใช้ซิงโครไนซ์ใน Java
ตัวอย่างเช่น: วัตถุเป็นเหมือนบ้านหลังใหญ่ประตูเปิดอยู่เสมอ มีห้องพักมากมายในบ้าน (นั่นคือวิธีการ)
ห้องเหล่านี้ล็อค (วิธีการซิงโครไนซ์) และไม่ล็อค (วิธีปกติ) มีกุญแจที่ประตูซึ่งสามารถเปิดห้องล็อคทั้งหมด
นอกจากนี้ฉันเปรียบเทียบกระทู้ทั้งหมดที่ต้องการเรียกวิธีการวัตถุกับผู้ที่ต้องการเข้าห้องในบ้านหลังนี้ มีเพียงหลายสิ่งเท่านั้นลองดูว่าสิ่งเหล่านี้ทำงานอย่างไร
ที่นี่ก่อนอื่นเราชี้แจงข้อกำหนดเบื้องต้นของเรา วัตถุมีวิธีการซิงโครไนซ์อย่างน้อยหนึ่งวิธีมิฉะนั้นจุดของคีย์นี้คืออะไร? แน่นอนว่าจะไม่มีหัวข้อดังกล่าวสำหรับเรา
ผู้ชายคนหนึ่งต้องการเข้าห้องล็อค เขามาที่ประตูบ้านและเห็นกุญแจที่นั่น (หมายความว่ายังไม่มีใครต้องการใช้ห้องที่ล็อค) ดังนั้นเขาจึงเดินขึ้นไปและได้กุญแจและใช้ห้องตามที่เขาวางแผนไว้ โปรดทราบว่าเขาจะคืนกุญแจทันทีหลังจากใช้ห้องล็อคทุกครั้ง แม้ว่าเขาต้องการใช้ห้องล็อคสองห้องติดต่อกันเขาจะคืนกุญแจเพื่อเรียกคืน ดังนั้นหลักการของการใช้คีย์ในกรณีปกติคือ: "ยืมตามที่คุณใช้และส่งคืนทันทีที่คุณใช้"
ในเวลานี้คนอื่นสามารถใช้ห้องที่ปลดล็อคเหล่านั้นโดยไม่มีข้อ จำกัด คนหนึ่งสามารถใช้หนึ่งห้องและสองคนสามารถใช้หนึ่งห้องโดยไม่มีข้อ จำกัด แต่ถ้ามีคนต้องการเข้าห้องล็อคเขาต้องวิ่งไปที่ประตูเพื่อดู แน่นอนถ้าคุณมีกุญแจคุณจะจากไป หากคุณไม่มีมันคุณสามารถรอได้เท่านั้น หากหลายคนกำลังรอคีย์นี้ใครจะได้รับคีย์ก่อนหลังจากกลับมา? ไม่รับประกัน เช่นเดียวกับผู้ชายในตัวอย่างก่อนหน้านี้ที่ต้องการใช้สองห้องที่ถูกล็อคติดต่อกันถ้ามีคนอื่นรอกุญแจอยู่ตรงกลางไม่มีการรับประกันว่าผู้ชายคนนี้จะได้รับอีกครั้ง (ข้อกำหนด Java ระบุอย่างชัดเจนว่ามันไม่ได้รับประกันในหลาย ๆ ที่เช่นระยะเวลาสำหรับด้าย. sleep () เพื่อกลับไปวิ่งหลังจากพักผ่อนด้ายที่มีลำดับความสำคัญเดียวกันจะถูกดำเนินการก่อน ในเงื่อนไขหนึ่ง แต่ขึ้นอยู่กับบทความมากมาย
เนื่องจากมีเงื่อนไขการตัดสินมากเกินไปหากคุณพูดมันอาจส่งผลกระทบต่อการส่งเสริมการขายของ Java หรืออาจเป็นเพราะการคุ้มครองทรัพย์สินทางปัญญา ซันให้สัญญากับฉันและผ่านมันไป ไม่มีอะไรผิดปกติกับมัน แต่ฉันเชื่อว่าความไม่แน่นอนเหล่านี้ไม่ได้ไม่แน่ใจทั้งหมด เพราะคอมพิวเตอร์ทำงานตามคำแนะนำ แม้ว่าปรากฏการณ์ดูเหมือนจะสุ่ม แต่ก็เป็นเรื่องปกติ ใครก็ตามที่ศึกษาคอมพิวเตอร์รู้ว่าชื่อทางวิทยาศาสตร์ของตัวเลขสุ่มในคอมพิวเตอร์คือหมายเลขหลอกหลอกซึ่งเขียนโดยคนที่ใช้วิธีการบางอย่างและพวกเขาก็ดูสุ่ม นอกจากนี้อาจเป็นเพราะมันยากเกินไปที่จะทำให้แน่ใจและไม่มีความหมายมากดังนั้นหากคุณไม่แน่ใจคุณไม่แน่ใจ -
ลองดูที่บล็อกรหัสการซิงโครไนซ์ มีความแตกต่างเล็กน้อยจากวิธีการซิงโครไนซ์
1. ในแง่ของขนาดบล็อกรหัสการซิงโครไนซ์มีขนาดเล็กกว่าวิธีการซิงโครไนซ์ คุณสามารถนึกถึงบล็อกรหัสการซิงโครไนซ์เป็นพื้นที่ในห้องที่ปลดล็อคคั่นด้วยหน้าจอที่ล็อค
2. บล็อกรหัสการซิงโครไนซ์ยังสามารถระบุคีย์ของการรับวัตถุอื่นได้ เช่นเดียวกับการระบุคีย์ที่จะปลดล็อกหน้าจอคุณสามารถใช้คีย์ของห้องนี้ได้ นอกจากนี้คุณยังสามารถระบุได้ว่ากุญแจของบ้านอื่นสามารถเปิดได้ ด้วยวิธีนี้คุณต้องวิ่งไปที่บ้านหลังอื่นเพื่อนำกุญแจนั้นและใช้กุญแจของบ้านหลังนั้นเพื่อเปิดหน้าจอที่ล็อคของบ้านหลังนี้
โปรดจำไว้ว่ากุญแจสำคัญสำหรับบ้านหลังอื่นที่คุณได้รับนั้นไม่ส่งผลกระทบต่อคนอื่น ๆ ที่เข้ามาในห้องโดยไม่มีล็อคในบ้านหลังนั้น
ทำไมต้องใช้บล็อกรหัสแบบซิงโครนัส? ฉันคิดว่ามันควรจะเป็นเช่นนี้: ก่อนอื่นส่วนการซิงโครไนซ์ของโปรแกรมมีผลกระทบอย่างมากต่อประสิทธิภาพการทำงานและวิธีการมักจะสร้างตัวแปรท้องถิ่นก่อนแล้วทำการดำเนินการบางอย่างเกี่ยวกับตัวแปรเหล่านี้เช่นการดำเนินการแสดงผล ฯลฯ ; และยิ่งโค้ดครอบคลุมโดยการซิงโครไนซ์มากเท่าไหร่ก็ยิ่งส่งผลกระทบต่อประสิทธิภาพมากขึ้นเท่านั้น ดังนั้นเรามักจะพยายาม จำกัด ผลกระทบของมัน
ทำอย่างไร? ซิงโครไนซ์บล็อกโค้ด เราซิงโครไนซ์เฉพาะสถานที่การซิงโครไนซ์ในวิธีเดียวเช่นการดำเนินการ
นอกจากนี้คุณลักษณะของบล็อกรหัสแบบซิงโครนัสที่สามารถระบุคีย์มีข้อได้เปรียบเพิ่มเติมซึ่งก็คือสามารถครอบครองคีย์ของวัตถุภายในระยะเวลาหนึ่ง คุณจำหลักการของการใช้กุญแจในสถานการณ์ปกติที่กล่าวถึงก่อนหน้านี้หรือไม่? ตอนนี้ไม่ใช่สถานการณ์ธรรมดา คีย์ที่คุณได้รับนั้นไม่เคยถูกส่งคืน แต่จะถูกส่งคืนเฉพาะเมื่อคุณออกจากบล็อกรหัสแบบซิงโครนัส
ฉันยังใช้คนที่อยู่ข้างหน้าซึ่งต้องการใช้สองห้องที่ล็อคไว้ในแถวเพื่อทำตัวอย่าง ฉันจะใช้อีกอันต่อไปได้อย่างไร ใช้บล็อกรหัสแบบซิงโครนัส ก่อนอื่นสร้างเธรดอื่นสร้างบล็อกรหัสแบบซิงโครนัสแล้วชี้ล็อคของบล็อกรหัสนั้นไปยังคีย์ของบ้าน จากนั้นเริ่มเธรดนั้น ตราบใดที่คุณสามารถคว้ากุญแจไปที่บ้านเมื่อป้อนบล็อกรหัสนั้นคุณสามารถเก็บไว้ได้จนกว่าคุณจะออกจากบล็อกรหัสนั้น กล่าวอีกนัยหนึ่งคุณสามารถสำรวจห้องที่ล็อคทั้งหมดในห้องนี้หรือแม้กระทั่งการนอนหลับ (10*60*1,000) และยังมี 1,000 เธรดรอกุญแจนี้ที่ประตู สนุกมาก
ที่นี่เราจะพูดคุยเกี่ยวกับความสัมพันธ์ระหว่างวิธีการนอนหลับ () และกุญแจ หากเธรดถูกบังคับให้นอนหลับ () หลังจากได้รับคีย์และยังไม่เสร็จเนื้อหาแบบซิงโครนัสคีย์ยังคงอยู่ที่นั่น คีย์จะไม่ถูกส่งคืนจนกว่าจะทำงานอีกครั้งและทำให้เนื้อหาแบบซิงโครนัสทั้งหมดเสร็จสมบูรณ์ โปรดจำไว้ว่าผู้ชายคนนั้นเหนื่อยกับการทำงานดังนั้นเขาจึงหยุดพักและเขาก็ไม่จบสิ่งที่เขาจะทำ เพื่อหลีกเลี่ยงคนอื่น ๆ ที่เข้ามาในห้องและทำให้ยุ่งเหยิงเขาต้องสวมใส่กุญแจเดียวในร่างกายของเขาแม้ว่าเขาจะนอนหลับ
ในที่สุดบางคนอาจถามว่าทำไมคุณต้องมีกุญแจเพื่อเปิดแทนกุญแจและประตู? ฉันคิดว่านี่เป็นเพราะความซับซ้อน แน่นอนว่าหนึ่งกุญแจและประตูเดียวปลอดภัยกว่า แต่มันจะเกี่ยวข้องกับปัญหามากมาย การสร้าง, การจัดเก็บ, การได้มา, ผลตอบแทน ฯลฯ ของกุญแจ ความซับซ้อนของมันอาจเพิ่มลำดับทางเรขาคณิตด้วยการเพิ่มวิธีการซิงโครไนซ์ซึ่งส่งผลกระทบอย่างรุนแรงต่อประสิทธิภาพ นี่คือการแลกเปลี่ยน วิธีที่ไม่พึงปรารถนาคือการเพิ่มความปลอดภัยเล็กน้อยส่งผลให้ประสิทธิภาพลดลงอย่างมีนัยสำคัญ
ตัวอย่างง่ายๆของการซิงโครไนซ์
Public Class TextThread {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {txtThread tt = new txtThread (); เธรดใหม่ (TT). start (); เธรดใหม่ (TT). start (); เธรดใหม่ (TT). start (); เธรดใหม่ (TT). start (); }} คลาส txtThread ใช้งาน runnable {int num = 100; string str = new String (); โมฆะสาธารณะ run () {ซิงโครไนซ์ (str) {ในขณะที่ (num> 0) {ลอง {thread.sleep (1); } catch (exception e) {e.getMessage (); } system.out.println (thread.currentthread (). getName () + "นี่คือ" + num--); -ในตัวอย่างข้างต้นเพื่อสร้างความแตกต่างของเวลานั่นคือโอกาสที่จะทำข้อผิดพลาด thread.sleep (10)
กลไกการสนับสนุนและการซิงโครไนซ์ของ Java สำหรับมัลติเธรดเป็นที่นิยมมาก ดูเหมือนว่าการใช้คำหลักที่ซิงโครไนซ์สามารถแก้ปัญหาของการซิงโครไนซ์ข้อมูลแบบมัลติเธรดที่ใช้ร่วมกันได้อย่างง่ายดาย อะไรกันแน่? นอกจากนี้ยังจำเป็นต้องมีความเข้าใจในเชิงลึกเกี่ยวกับบทบาทของคำหลักที่ซิงโครไนซ์ก่อนที่คุณจะสามารถสรุปได้
โดยทั่วไปคำหลักที่ซิงโครไนซ์สามารถใช้เป็นตัวดัดแปลงของฟังก์ชั่นหรือเป็นคำสั่งภายในฟังก์ชั่นซึ่งเป็นวิธีการซิงโครไนซ์และบล็อกคำสั่งการซิงโครไนซ์ที่มักจะกล่าวถึง หากคุณจำแนกได้อย่างระมัดระวังมากขึ้นการซิงโครไนซ์สามารถทำหน้าที่กับตัวแปรอินสแตนซ์การอ้างอิงวัตถุฟังก์ชั่นคงที่และตัวอักษรคลาส (ชื่อคลาสค่าคงที่ตามตัวอักษร)
ก่อนที่เราจะอธิบายเพิ่มเติมเพิ่มเติมเราต้องชี้แจงบางจุด:
A. ไม่ว่าจะเป็นการเพิ่มคำหลักที่ซิงโครไนซ์ลงในวิธีการหรือวัตถุการล็อคที่ได้รับนั้นเป็นวัตถุแทนที่จะรักษาส่วนหนึ่งของรหัสหรือฟังก์ชั่นเป็นล็อคและวิธีการซิงโครไนซ์มีแนวโน้มที่จะเป็นไปได้มากกว่า
การเข้าถึงวัตถุไปยังเธรดของเขา
B. แต่ละวัตถุมีเพียงล็อคเดียวที่เกี่ยวข้อง
C. การใช้การซิงโครไนซ์ต้องใช้ค่าใช้จ่ายของระบบจำนวนมากเป็นค่าใช้จ่ายและอาจทำให้เกิดการหยุดชะงักดังนั้นพยายามหลีกเลี่ยงการควบคุมการซิงโครไนซ์ที่ไม่จำเป็น
ถัดไปให้หารือเกี่ยวกับผลกระทบของการซิงโครไนซ์โดยใช้สถานที่ต่าง ๆ ในรหัส:
สมมติว่า P1 และ P2 เป็นวัตถุที่แตกต่างกันของคลาสเดียวกันคลาสนี้กำหนดบล็อกการซิงโครไนซ์หรือวิธีการซิงโครไนซ์ในสถานการณ์ต่อไปนี้และ P1 และ P2 สามารถเรียกพวกเขาได้
1. เมื่อใช้ซิงโครไนซ์เป็นตัวดัดแปลงฟังก์ชันโค้ดตัวอย่างมีดังนี้:
โมฆะโมฆะที่ซิงโครไนซ์สาธารณะ () {// ….}นี่คือวิธีการซิงโครไนซ์ ดังนั้นวัตถุใดที่ถูกล็อคในเวลานี้? สิ่งที่ล็อคคือการเรียกวัตถุวิธีการแบบซิงโครนัสนี้ กล่าวคือเมื่อวัตถุ P1 ดำเนินการวิธีการซิงโครไนซ์นี้ในเธรดที่แตกต่างกันการยกเว้นซึ่งกันและกันจะเกิดขึ้นระหว่างพวกเขาเพื่อให้ได้ผลของการซิงโครไนซ์ อย่างไรก็ตามวัตถุอื่น P2 ที่สร้างขึ้นโดยคลาสที่วัตถุนี้เป็นของสามารถเรียกวิธีนี้โดยพลการโดยเพิ่มคำหลักที่ซิงโครไนซ์
รหัสตัวอย่างข้างต้นเทียบเท่ากับรหัสต่อไปนี้:
โมฆะสาธารณะ Methodaaa () {ซิงโครไนซ์ (นี่) // (1) {// … .. }}(1) จุดนี้หมายถึงอะไร? มันหมายถึงวัตถุที่เรียกวิธีนี้เช่น P1 จะเห็นได้ว่าวิธีการซิงโครไนซ์นั้นเป็นหลักในการใช้การซิงโครไนซ์กับการอ้างอิงวัตถุ เฉพาะเธรดที่ได้รับการล็อควัตถุ P1 เท่านั้นที่สามารถเรียกใช้วิธีการซิงโครไนซ์ P1 สำหรับ P2 ล็อค P1 ไม่มีส่วนเกี่ยวข้องกับมัน โปรแกรมอาจกำจัดการควบคุมกลไกการซิงโครไนซ์ในสถานการณ์นี้ทำให้เกิดความสับสนของข้อมูล: (
2. ซิงโครไนซ์บล็อกตัวอย่างมีดังนี้:
โมฆะโมฆะสาธารณะ 3 (SOMEOBJECT SO) {ซิงโครไนซ์ (SO) {// … .. }}ในเวลานี้ล็อคเป็นวัตถุของ SO ใครก็ตามที่ได้รับล็อคสามารถเรียกใช้รหัสที่ควบคุมได้ เมื่อมีวัตถุที่ชัดเจนเป็นล็อคคุณสามารถเขียนโปรแกรมเช่นนี้ได้ แต่เมื่อไม่มีวัตถุที่ชัดเจนว่าเป็นล็อคและเพียงแค่ต้องการรหัสเพื่อซิงโครไนซ์คุณสามารถสร้างตัวแปรอินสแตนซ์พิเศษ (ต้องเป็นวัตถุ) เพื่อทำหน้าที่เป็นล็อค:
Class Foo ใช้งาน Runnable {Private Byte [] Lock = New Byte [0]; // อินสแตนซ์พิเศษตัวแปรโมฆะสาธารณะเมธอด () {ซิงโครไนซ์ (ล็อค) {// …}} // … .. }หมายเหตุ: วัตถุอาร์เรย์ไบต์ที่มีความยาวเป็นศูนย์นั้นประหยัดกว่าวัตถุใด ๆ ในการสร้างรหัสไบต์ที่รวบรวมได้: มีเพียง 3 opcodes ที่จำเป็นในการสร้างวัตถุไบต์ที่มีความยาวเป็นศูนย์ในขณะที่วัตถุล็อค = วัตถุใหม่ () ต้องใช้ 7 opcodes
3. ใช้ฟังก์ชั่นแบบคงที่รหัสตัวอย่างมีดังนี้:
คลาส foo {public synchronized static methodaaa () // ฟังก์ชั่นคงที่ซิงโครไนซ์ {// …. } โมฆะสาธารณะ MethodBBB () {ซิงโครไนซ์ (foo.class) // คลาสตามตัวอักษร (ค่าคงที่ชื่อคลาสของคลาส)}}เมธอด bbbb () ในรหัสใช้ตัวอักษรคลาสเป็นล็อค มันมีผลเช่นเดียวกับฟังก์ชั่นคงที่แบบซิงโครไนซ์ ล็อคที่ได้รับนั้นพิเศษมาก มันเป็นคลาสที่วัตถุที่เรียกวิธีนี้เป็นของ (คลาสไม่ใช่วัตถุเฉพาะที่สร้างโดยคลาสนี้)
ฉันจำได้ว่าในหนังสือ "Java ที่มีประสิทธิภาพ" ฉันเห็นว่าการใช้ foo.class และ p1.getClass () เป็นล็อคแบบซิงโครนัสนั้นแตกต่างกันและ P1.getClass () ไม่สามารถใช้เพื่อบรรลุวัตถุประสงค์ในการล็อคคลาสนี้ P1 หมายถึงวัตถุที่สร้างขึ้นโดยคลาส FOO
สามารถอนุมานได้ว่าหากคลาสกำหนดฟังก์ชั่นสแตติกแบบซิงโครไนซ์ A และฟังก์ชันอินสแตนซ์ที่ซิงโครไนซ์ B ดังนั้น OBJ วัตถุเดียวกันของคลาสนี้จะไม่เป็นการซิงโครไนซ์เมื่อเข้าถึงสองวิธี A และ B ในหลายเธรดเนื่องจากล็อคของพวกเขาแตกต่างกัน การล็อคของวิธี A คือ Object OBJ ในขณะที่ Lock of B คือคลาสที่ OBJ เป็นของ
สรุปมีดังนี้:
การค้นหาว่าล็อคแบบซิงโครไนซ์ของวัตถุใดที่สามารถช่วยเราออกแบบโปรแกรมหลายเธรดที่ปลอดภัยยิ่งขึ้น นอกจากนี้ยังมีเคล็ดลับที่จะทำให้การเข้าถึงทรัพยากรที่ใช้ร่วมกันแบบซิงโครนัสมีความปลอดภัยมากขึ้น:
1. กำหนดตัวแปรอินสแตนซ์ของ Method + GET แทนที่จะเป็นตัวแปรอินสแตนซ์ของสาธารณะ/ป้องกัน หากตัวแปรถูกกำหนดเป็นสาธารณะวัตถุสามารถข้ามการควบคุมของวิธีการซิงโครไนซ์และรับโดยตรงและเปลี่ยน นี่เป็นหนึ่งในวิธีการใช้งานมาตรฐานของ Javabean
2. หากตัวแปรอินสแตนซ์เป็นวัตถุเช่นอาร์เรย์หรืออาร์เรย์ลิสต์ดังนั้นวิธีการข้างต้นยังคงไม่ปลอดภัยเพราะเมื่อวัตถุภายนอกได้รับการอ้างอิงไปยังวัตถุอินสแตนซ์ผ่านวิธีการรับและชี้ไปที่วัตถุอื่นตัวแปรส่วนตัวจะเปลี่ยนซึ่งไม่อันตรายมาก ในเวลานี้คุณต้องเพิ่มการซิงโครไนซ์กับวิธีการ GET และส่งคืนโคลน () ของวัตถุส่วนตัวนี้เพื่อให้ผู้โทรได้รับการอ้างอิงไปยังสำเนาวัตถุ
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น