บทความแบ่งปัน 4 ตัวอย่างของคำอธิบายโดยละเอียดเกี่ยวกับการซิงโครไนซ์
1. ไม่ว่าจะเพิ่มคำหลักที่ซิงโครไนซ์
Public Class ThreadTest {โมฆะสาธารณะคงที่หลัก (String [] args) {ตัวอย่าง = ตัวอย่างใหม่ (); เธรด t1 = ใหม่เธรด 1 (ตัวอย่าง); เธรด t2 = ใหม่เธรด 1 (ตัวอย่าง); t1.start (); t2.start (); }} ตัวอย่างคลาส {public synchronized void ไอเสีย () {สำหรับ (int i = 0; i <5; ++ i) {ลอง {thread.sleep (1000); } catch (interruptedException e) {e.printStackTrace (); } system.out.println ("excute:" + i); }}} คลาส Thread1 ขยายเธรด {ตัวอย่างส่วนตัวตัวอย่าง; Public Thread1 (ตัวอย่างตัวอย่าง) {this.example = ตัวอย่าง; } @Override โมฆะสาธารณะเรียกใช้ () {example.excute (); -ผลลัพธ์ผลลัพธ์ของคำหลักที่ซิงโครไนซ์มีดังนี้
ชุด 0-4 จะเป็นเอาต์พุตก่อนจากนั้นชุดถัดไปจะเป็นเอาต์พุตและสองเธรดจะถูกดำเนินการตามลำดับ
กระตุ้น: 0
กระตุ้น: 1
กระตุ้น: 2
กระตุ้น: 3
กระตุ้น: 4
กระตุ้น: 0
กระตุ้น: 1
กระตุ้น: 2
กระตุ้น: 3
กระตุ้น: 4
ผลลัพธ์ผลลัพธ์ของคำหลักที่ซิงโครไนซ์มีดังนี้
สองเธรดดำเนินการวิธีการกระตุ้นพร้อมกันและพร้อมกัน
กระตุ้น: 0
กระตุ้น: 0
กระตุ้น: 1
กระตุ้น: 1
กระตุ้น: 2
กระตุ้น: 2
กระตุ้น: 3
กระตุ้น: 3
กระตุ้น: 4
กระตุ้น: 4
2. สถานการณ์หลายเธรดของหลายวิธี
Public Class ThreadTest {โมฆะสาธารณะคงที่หลัก (String [] args) {ตัวอย่าง = ตัวอย่างใหม่ (); เธรด t1 = ใหม่เธรด 1 (ตัวอย่าง); เธรด t2 = thread2 (ตัวอย่าง); t1.start (); t2.start (); }} ตัวอย่างคลาส {public synchronized void ไอเสีย () {สำหรับ (int i = 0; i <5; ++ i) {ลอง {thread.sleep (1000); } catch (interruptedException e) {e.printStackTrace (); } system.out.println ("excute:" + i); }} โมฆะที่ซิงโครไนซ์สาธารณะเป็นโมฆะ iscid1 () {สำหรับ (int i = 0; i <5; ++ i) {ลอง {thread.sleep (1,000); } catch (interruptedException e) {e.printStackTrace (); } system.out.println ("excute1:" + i); }}} คลาส Thread1 ขยายเธรด {ตัวอย่างส่วนตัวตัวอย่าง; Public Thread1 (ตัวอย่างตัวอย่าง) {this.example = ตัวอย่าง; } @Override โมฆะสาธารณะเรียกใช้ () {example.excute (); }} คลาส Thread2 ขยายเธรด {ตัวอย่างส่วนตัวตัวอย่าง; Public Thread2 (ตัวอย่างตัวอย่าง) {this.example = ตัวอย่าง; } @Override โมฆะสาธารณะ Run () {example.excute1 (); -ผลการดำเนินการมีดังนี้
เดียวกันจะถูกดำเนินการตามลำดับและหนึ่งเธรดจะถูกดำเนินการก่อนที่จะดำเนินการเธรดอื่น
กระตุ้น: 0
กระตุ้น: 1
กระตุ้น: 2
กระตุ้น: 3
กระตุ้น: 4
excute1: 0
excute1: 1
excute1: 2
excute1: 3
Exclusive1: 4
หากคำหลักที่ซิงโครไนซ์ถูกลบออกไปสองวิธีจะถูกดำเนินการพร้อมกันและไม่มีอิทธิพลร่วมกัน
แต่ตามที่เขียนไว้ในรูทีนย่อยตัวอย่างแม้แต่สองวิธี:
ผลการดำเนินการจะเป็นเอาต์พุตของเธรดหนึ่งเสมอจากนั้นการดำเนินการของเธรดอื่น
ภาพประกอบ:
หากวัตถุมีวิธีการซิงโครไนซ์หลายวิธีและเธรดได้ป้อนวิธีการซิงโครไนซ์ในช่วงเวลาหนึ่งเธรดอื่น ๆ ไม่สามารถเข้าถึงวิธีการซิงโครไนซ์ใด ๆ ของวัตถุก่อนที่จะดำเนินการวิธีการ
สรุปแล้ว:
เมื่อคำหลักที่ซิงโครไนซ์ปรับเปลี่ยนวิธีการวิธีนี้เรียกว่าวิธีการซิงโครไนซ์
แต่ละวัตถุในชวามีล็อคหรือจอภาพ เมื่อเธรดเข้าถึงวิธีที่ซิงโครไนซ์ของวัตถุวัตถุจะถูกล็อคและไม่มีเธรดอื่นใดที่สามารถเข้าถึงวิธีการซิงโครไนซ์ของวัตถุ (นี่หมายถึงวิธีการซิงโครไนซ์ทั้งหมดไม่ใช่แค่วิธีเดียวกัน) มันไม่ได้จนกว่าเธรดก่อนหน้าจะเสร็จสิ้นวิธีการดำเนินการ (หรือโยนข้อยกเว้น) การล็อคของวัตถุจะถูกปล่อยออกมาเพื่อให้เธรดอื่นสามารถเข้าถึงวิธีการซิงโครไนซ์ของวัตถุอีกครั้ง
โปรดทราบว่าวัตถุถูกล็อคในเวลานี้ หากเป็นวัตถุที่แตกต่างกันไม่มีความสัมพันธ์ที่ จำกัด ระหว่างวัตถุ
เมื่อพยายามสร้างวัตถุเธรดที่สองในรหัสวัตถุตัวอย่างใหม่จะถูกส่งผ่านแล้วไม่มีข้อ จำกัด ระหว่างการดำเนินการของสองเธรด
3. วิธีการซิงโครไนซ์แบบคงที่
เมื่อวิธีการแก้ไขคำหลักที่ซิงโครไนซ์ได้รับการแก้ไขด้วยแบบคงที่ก็มีการกล่าวก่อนหน้านี้ว่าวิธีการซิงโครไนซ์แบบไม่คงที่จะล็อควัตถุ แต่วิธีการคงที่ไม่ได้อยู่ในวัตถุ แต่คลาสและจะล็อควัตถุคลาสของคลาสที่วิธีนี้ตั้งอยู่
Public Class ThreadTest {โมฆะสาธารณะคงที่หลัก (String [] args) {ตัวอย่าง = ตัวอย่างใหม่ (); ตัวอย่างตัวอย่าง 2 = ตัวอย่างใหม่ (); เธรด t1 = ใหม่เธรด 1 (ตัวอย่าง); เธรด t2 = thread2 (ตัวอย่าง 2); t1.start (); t2.start (); }} ตัวอย่างคลาส {public synchronized static void ไอเสีย () {สำหรับ (int i = 0; i <5; ++ i) {ลอง {thread.sleep (1000); } catch (interruptedException e) {e.printStackTrace (); } system.out.println ("excute:" + i); }} public synchronized static void exid1 () {สำหรับ (int i = 0; i <5; ++ i) {ลอง {thread.sleep (1000); } catch (interruptedException e) {e.printStackTrace (); } system.out.println ("excute1:" + i); }}} คลาส Thread1 ขยายเธรด {ตัวอย่างส่วนตัวตัวอย่าง; Public Thread1 (ตัวอย่างตัวอย่าง) {this.example = ตัวอย่าง; } @Override โมฆะสาธารณะเรียกใช้ () {example.excute (); }} คลาส Thread2 ขยายเธรด {ตัวอย่างส่วนตัวตัวอย่าง; Public Thread2 (ตัวอย่างตัวอย่าง) {this.example = ตัวอย่าง; } @Override โมฆะสาธารณะ Run () {example.excute1 (); -ผลการดำเนินการมีดังนี้
กระตุ้น: 0
กระตุ้น: 1
กระตุ้น: 2
กระตุ้น: 3
กระตุ้น: 4
excute1: 0
excute1: 1
excute1: 2
excute1: 3
Exclusive1: 4
หากไม่มีตัวดัดแปลงคงที่และสองเธรดผ่านวัตถุที่แตกต่างกันพวกเขาจะถูกดำเนินการพร้อมกันในเวลาเดียวกัน
ดังนั้นหากเป็นวิธีการคงที่ (execute () และ execute2 () ทั้งสองมีคำหลักที่เพิ่มเข้ามา) แม้ว่าวัตถุตัวอย่างที่แตกต่างกันจะถูกส่งผ่านไปยังสองเธรดสองเธรดทั้งสองยังคงถูก จำกัด ซึ่งกันและกัน หนึ่งจะต้องดำเนินการก่อนและจากนั้นอีกครั้ง
สรุปแล้ว:
หากวิธีการซิงโครไนซ์เป็นแบบคงที่เมื่อเธรดเข้าถึงวิธีการจะไม่ล็อควัตถุที่วิธีการซิงโครไนซ์อยู่ แต่วัตถุคลาสที่สอดคล้องกับคลาสที่มีวิธีการซิงโครไนซ์ ในชวาไม่ว่าจะมีวัตถุกี่ชิ้นวัตถุเหล่านี้จะสอดคล้องกับวัตถุคลาสที่ไม่ซ้ำกัน ดังนั้นเมื่อเธรดเข้าถึงสองวิธีแบบคงที่และซิงโครไนซ์ของวัตถุสองชิ้นในคลาสเดียวกันลำดับการดำเนินการของพวกเขาก็เป็นลำดับนั่นคือหนึ่งเธรดหนึ่งจะดำเนินการวิธีการก่อนและเธรดอื่น ๆ จะเริ่มหลังจากการดำเนินการเสร็จสมบูรณ์
4. บล็อกซิงโครไนซ์
ซิงโครไนซ์ (วัตถุ)
-
-
หมายความว่าเธรดจะล็อควัตถุวัตถุเมื่อดำเนินการ (โปรดทราบว่าวัตถุนี้สามารถเป็นวัตถุของคลาสใดก็ได้หรือคุณสามารถใช้คำหลักนี้ได้)
ด้วยวิธีนี้คุณสามารถระบุวัตถุที่ล็อคได้ด้วยตัวเอง
Public Class ThreadTest {โมฆะสาธารณะคงที่หลัก (String [] args) {ตัวอย่าง = ตัวอย่างใหม่ (); เธรด t1 = ใหม่เธรด 1 (ตัวอย่าง); เธรด t2 = thread2 (ตัวอย่าง); t1.start (); t2.start (); }} ตัวอย่างคลาส {public void exid () {ซิงโครไนซ์ (นี่) {สำหรับ (int i = 0; i <5; ++ i) {ลอง {thread.sleep (1000); } catch (interruptedException e) {e.printStackTrace (); } system.out.println ("excute:" + i); }}} โมฆะสาธารณะไอเสีย 1 () {ซิงโครไนซ์ (นี่) {สำหรับ (int i = 0; i <5; ++ i) {ลอง {thread.sleep (1000); } catch (interruptedException e) {e.printStackTrace (); } system.out.println ("excute1:" + i); }}}}}} เธรดคลาส 1 ขยายเธรด {ตัวอย่างตัวอย่างส่วนตัว; Public Thread1 (ตัวอย่างตัวอย่าง) {this.example = ตัวอย่าง; } @Override โมฆะสาธารณะเรียกใช้ () {example.excute (); }} คลาส Thread2 ขยายเธรด {ตัวอย่างส่วนตัวตัวอย่าง; Public Thread2 (ตัวอย่างตัวอย่าง) {this.example = ตัวอย่าง; } @Override โมฆะสาธารณะ Run () {example.excute1 (); -ผลการดำเนินการมีดังนี้
กระตุ้น: 0
กระตุ้น: 1
กระตุ้น: 2
กระตุ้น: 3
กระตุ้น: 4
excute1: 0
excute1: 1
excute1: 2
excute1: 3
Exclusive1: 4
เอฟเฟกต์ที่ทำได้โดย ตัวอย่างโปรแกรม 4 นั้น เหมือนกับของโปรแกรมตัวอย่าง 2 เธรดทั้งสองจะถูกดำเนินการตามลำดับแทนที่จะเป็นพร้อมกัน เมื่อเธรดหนึ่งดำเนินการวัตถุวัตถุจะถูกล็อคและเธรดอื่นไม่สามารถเรียกใช้งานบล็อกที่เกี่ยวข้องได้
วิธีการซิงโครไนซ์นั้นเทียบเท่ากับการห่อข้อความทั้งหมดในวิธีการด้วยบล็อกที่ซิงโครไนซ์แล้วส่งคำหลักนี้ในวงเล็บของบล็อกที่ซิงโครไนซ์ แน่นอนถ้ามันเป็นวิธีการคงที่วัตถุคลาสจะต้องถูกล็อค
บางทีโค้ดเพียงไม่กี่บรรทัดในวิธีการจะเกี่ยวข้องกับปัญหาการซิงโครไนซ์เธรดดังนั้นบล็อกที่ซิงโครไนซ์จะควบคุมการเข้าถึงหลายเธรดมากกว่าวิธีการซิงโครไนซ์ เฉพาะเนื้อหาในบล็อกซิงโครไนซ์ไม่สามารถเข้าถึงได้หลายเธรดในเวลาเดียวกันและข้อความอื่น ๆ ในวิธีการยังสามารถเข้าถึงได้โดยหลายเธรดในเวลาเดียวกัน (รวมถึงก่อนและหลังบล็อกซิงโครไนซ์)
สรุปแล้ว:
วิธีการซิงโครไนซ์ เป็นตัวควบคุมที่มีความละเอียดหยาบ ในช่วงเวลาหนึ่งเธรดเดียวเท่านั้นที่สามารถเรียกใช้วิธีการซิงโครไนซ์
บล็อกที่ซิงโครไนซ์ เป็นการควบคุมการเกิดพร้อมกันอย่างละเอียดซึ่งซิงโครไนซ์รหัสในบล็อกเท่านั้น รหัสอื่น ๆ ที่อยู่ในวิธีการและอื่น ๆ นอกเหนือจากบล็อกที่ซิงโครไนซ์สามารถเข้าถึงได้โดยหลายเธรดในเวลาเดียวกัน
ข้างต้นเป็นเรื่องเกี่ยวกับวิธีการซิงโครไนซ์บล็อกแบบซิงโครไนซ์ของการเขียนโปรแกรมมัลติเธรด Java ฉันหวังว่ามันจะเป็นประโยชน์กับการเรียนรู้ของทุกคน