Syncการทำให้เป็นเกียรติใน Java
ความหมายของ Syncการทำให้เป็นเกียรติใน Java?
In Javaการซิงโครไนซ์หมายถึงความสามารถในการควบคุมการเข้าถึงทรัพยากรที่ใช้ร่วมกันของเธรดหลายเธรด ถือเป็นตัวเลือกที่เหมาะสมที่สุดในกรณีที่เราต้องการให้เธรดเดียวเท่านั้นที่สามารถเข้าถึงทรัพยากรที่ใช้ร่วมกันได้
แนวทางการดำเนินการนี้มักเรียกว่าการเขียนโปรแกรมแบบอะซิงโครนัส นอกจากนี้ยังมีเธรดบนโปรเซสเซอร์เหล่านี้ ซึ่งเป็นกระบวนการน้ำหนักเบาที่สามารถดำเนินการคำสั่งพร้อมกันได้
ประเภทของ Syncการทำให้เป็นพงศาวดาร
มีวิธีการซิงโครไนซ์ 2 ประเภทใน Java:
1) การซิงโครไนซ์กระบวนการ
2) การซิงโครไนซ์เธรด
มาศึกษา Thread และ การซิงโครไนซ์กระบวนการ ในรายละเอียด.
การซิงโครไนซ์กระบวนการ: จัดการการซิงโครไนซ์ระหว่างโปรแกรม ตัวอย่างเช่น โปรแกรมเช่น `Microsoft Word` และ `Acrobat reader` ทำงานเป็นกระบวนการเดี่ยวกัน
การซิงโครไนซ์เธรด: การดำเนินการพร้อมกันของทรัพยากรที่สำคัญโดยเธรดตั้งแต่สองตัวขึ้นไปเรียกว่าเธรด Syncการทำให้เป็นเกียรติ คุณสามารถจัดกลุ่มเพิ่มเติมเพื่อการสื่อสารแบบเอกสิทธิ์เฉพาะบุคคลและระหว่างเธรดได้
ล็อคอินคืออะไร. Java?
ล็อคอิน Java ถูกสร้างขึ้นโดยมีเอนทิตีภายในที่เรียกว่ามอนิเตอร์หรือการล็อค วัตถุทั้งหมดมีการล็อคที่เกี่ยวข้องกัน ดังนั้น เธรดที่ต้องการการเข้าถึงฟิลด์ของออบเจ็กต์อย่างสม่ำเสมอจะต้องได้รับการล็อคของออบเจ็กต์ก่อนที่จะเข้าถึง และจะปล่อยการล็อคเมื่องานเสร็จสิ้น สิ่งนี้ทำให้แน่ใจได้ว่ามีเธรดเดียวเท่านั้นที่เข้าถึงข้อมูลที่ใช้ร่วมกันในแต่ละครั้ง
โปรแกรมมัลติเธรดพร้อมการซิงโครไนซ์
โปรแกรมแบบมัลติเธรด เป็นวิธีการหรือบล็อกที่ได้รับการปกป้องจากการแทรกแซงจากเธรดอื่นๆ ที่ใช้ทรัพยากรร่วมกัน โดยระบุโดยใช้คีย์เวิร์ด `synchronized`
การใช้วิธีการซิงโครไนซ์
วิธีการใดๆ ที่ถูกประกาศให้ซิงโครไนซ์จะเรียกว่าวิธีการซิงโครไนซ์ นอกจากนี้ยังใช้เพื่อล็อกอ็อบเจ็กต์สำหรับทรัพยากรที่ใช้ร่วมกัน ดังนั้น เมื่อเธรดเรียกใช้วิธีการซิงโครไนซ์ เธรดจะเข้าครอบครองการล็อกสำหรับอ็อบเจ็กต์นั้นโดยอัตโนมัติและปล่อยเมื่อเสร็จสิ้นงาน
หมายเหตุ คีย์เวิร์ดซิงโครไนซ์ไม่สามารถทำงานร่วมกับคลาสและตัวแปรได้ ใช้ได้เฉพาะเมธอดและบล็อกเท่านั้นกับคีย์เวิร์ดนี้
ทำไมต้องใช้ Syncวิธีการขัดจังหวะ?
- มันถูกใช้สำหรับล็อควัตถุสำหรับทรัพยากรที่ใช้ร่วมกัน
- วัตถุจะได้รับการล็อคทุกครั้งที่มีการเรียกใช้วิธีการซิงโครไนซ์
- ล็อคจะไม่ปล่อยจนกว่าด้ายจะทำงานได้สมบูรณ์
ไวยากรณ์:
Acess_modifiers synchronized return_type method_name (Method_Parameters) { }
class MathService { synchronized void getSumOfArray(int[] numbers) { int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); } }
คำอธิบายของรหัส:
เรียกใช้ตัวอย่างนี้และสังเกตว่าเธรด `0` ได้รับการล็อกของวัตถุ `mathService` ก่อน และใช้การล็อกนี้โดยเฉพาะจนกว่าจะดำเนินการเสร็จสิ้น เธรด `0` และ `1` ไม่ได้ถูกแทรกอยู่ในโค้ดนี้ ผลลัพธ์เป็นไปตามที่แสดงด้านล่าง
Output:
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
การใช้บล็อคแบบซิงโครไนซ์
สมมติว่าคุณไม่ต้องการซิงโครไนซ์วิธีการทั้งหมด แต่คุณต้องการซิงโครไนซ์โค้ดเพียงไม่กี่บรรทัด ในเวลานั้น Syncบล็อค hronized ช่วยในการซิงโครไนซ์ที่เลือก Java รหัส. Syncสามารถเข้าถึงการล็อควิธีการแบบ hronized บนวิธีการ ในขณะที่การล็อคบล็อกแบบซิงโครไนซ์จะเข้าถึงบนวัตถุ
class MathService { void getSumOfArray(int[] numbers) { synchronized (this){ int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); } }
คำอธิบายรหัส:
เมื่อรันโค้ดนี้แล้ว คุณจะสังเกตเห็นว่าโค้ดทำงานโดยไม่มีการรบกวนใดๆ ในเมธอดซิงโครไนซ์ ล็อกจะถูกใช้โดยเมธอด แต่ในบล็อกซิงโครไนซ์ ล็อกจะถูกใช้โดยอ็อบเจกต์ ตรวจสอบว่าเอาต์พุตเป็นดังที่แสดงด้านล่าง
Output:
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
คำอธิบายของรหัส:
เมื่อคุณรันโค้ดนี้ คุณจะสังเกตเห็นว่าโค้ดทำงานได้โดยไม่มีการรบกวน ซึ่งเป็นสิ่งที่เราคาดหวังไว้ ในวิธีการแบบซิงโครไนซ์ ล็อกจะถูกใช้โดยวิธีการนี้ แต่ในวิธีการแบบบล็อกแบบซิงโครไนซ์ ล็อกจะถูกใช้โดยอ็อบเจกต์
การใช้การซิงโครไนซ์แบบคงที่
In Java การซิงโครไนซ์ หากมีวัตถุมากกว่าหนึ่งชิ้น เธรดสองเธรดอาจรับล็อกและเข้าสู่บล็อกที่ซิงโครไนซ์ได้ โดยมีล็อกแยกกันสำหรับแต่ละวัตถุ เพื่อหลีกเลี่ยงปัญหานี้ สามารถใช้การซิงโครไนซ์แบบคงที่ได้ Syncคำหลักที่ได้รับการขัดเกลาจะถูกใช้ก่อนวิธีคงที่
หมายเหตุ ในการซิงโครไนซ์แบบคงที่ การล็อคการเข้าถึงจะอยู่ที่คลาส ไม่ใช่อยู่ที่วัตถุและวิธีการ
รหัสเพื่อแสดงปัญหาของการล็อควัตถุหลายรายการ
class MathService { synchronized void getSumOfArray(int[] numbers) { int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); MathService mathService1 = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); Thread threadThree = new Thread(() -> mathService1.getSumOfArray(new int[]{10, 11, 12})); Thread threadFour = new Thread(() -> mathService1.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); threadThree.start(); threadFour.start(); } }
คำอธิบายของรหัส:
เมื่อเราสร้าง `MathService` อีกตัวอย่างหนึ่ง เราจะแนะนำการรบกวนในเธรด เนื่องจากเธรดเหล่านั้นจะถูกแทรกเข้ากับวัตถุทั้งสอง โปรดทราบว่าเธรด `0` และเธรด `2` ถูกแทรกสลับกับวัตถุทั้งสอง ในขณะที่เธรด `1` และ `3` ถูกแทรกสลับกับวัตถุทั้งสอง
Output:
Thread-0 adds 0 to 10 to get -> 10 Thread-2 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-2 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-2 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-3 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-3 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63 Thread-3 adds 41 to 22 to get -> 63
รหัสเดียวกันโดยใช้วิธีการซิงโครไนซ์แบบคงที่
class MathService { synchronized static void getSumOfArray(int[] numbers) { int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); MathService mathService1 = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); Thread threadThree = new Thread(() -> mathService1.getSumOfArray(new int[]{10, 11, 12})); Thread threadFour = new Thread(() -> mathService1.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); threadThree.start(); threadFour.start(); } }
เรียกใช้โค้ดด้านบนและโปรดทราบว่าขณะนี้เราได้กำจัดการรบกวนของเธรดแล้ว ผลลัพธ์ของโค้ดแสดงอยู่ด้านล่าง
Output:
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-3 adds 0 to 20 to get -> 20 Thread-3 adds 20 to 21 to get -> 41 Thread-3 adds 41 to 22 to get -> 63 Thread-2 adds 0 to 10 to get -> 10 Thread-2 adds 10 to 11 to get -> 21 Thread-2 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
ข้อดีของการใช้การซิงโครไนซ์
นี่คือข้อดีของการทำงานกับแอปพลิเคชันที่ทำงานพร้อมกัน:
- วัตถุประสงค์หลักของการซิงโครไนซ์ใน Java คือการป้องกันข้อมูลที่ไม่สอดคล้องกันโดยการป้องกันการรบกวนของเธรด
- คีย์เวิร์ดซิงโครไนซ์ใน Java ให้การล็อคซึ่งช่วยให้มั่นใจถึงการเข้าถึงทรัพยากรที่ใช้ร่วมกันแบบแยกกันและป้องกันการแข่งขันข้อมูล
- นอกจากนี้ยังป้องกันการเรียงลำดับคำสั่งรหัสใหม่ด้วย ผู้รวบรวมซึ่งอาจทำให้เกิดปัญหาพร้อมกันที่ละเอียดอ่อนได้หากเราไม่ใช้คีย์เวิร์ดที่ไม่แน่นอนหรือแบบซิงโครไนซ์
- Syncคำหลักที่ได้รับการขัดจังหวะจะอ่านข้อมูลจากหน่วยความจำหลักมากกว่าแคชและเมื่อปลดล็อก
- นอกจากนี้ยังล้างการดำเนินการเขียนจากหน่วยความจำหลัก ช่วยขจัดข้อผิดพลาดจากความไม่สอดคล้องของหน่วยความจำ
ข้อเสียของ Syncกลไกการขัดสี
Syncกลไกการขัดจังหวะมีประสิทธิภาพต่ำ
ตัวอย่างเช่น
- สมมติว่ามีห้ากระบวนการ A1, A2, A3, A4 และ A5
- พวกเขากำลังรอให้ทรัพยากรที่ใช้ร่วมกันเข้าถึงทีละเธรด
- กระบวนการทั้งหมดจะถูกปล่อยให้รอ ดังนั้นกระบวนการสุดท้ายในคิวต้องรอจนกว่ากระบวนการอื่นๆ ทั้งหมดจะเสร็จสมบูรณ์
สรุป
- Syncการทำเวลาหมายถึงความสามารถในการควบคุมการเข้าถึงหลายเธรดไปยังทรัพยากรที่ใช้ร่วมกัน
- Java มีวิธีการซิงโครไนซ์ 2 ประเภท: 1) การซิงโครไนซ์กระบวนการและ 2) การซิงโครไนซ์เธรด
- ล็อคอิน Java ถูกสร้างขึ้นโดยมีเอนทิตีภายในที่เรียกว่ามอนิเตอร์หรือการล็อค
- โปรแกรมมัลติเธรดคือวิธีการหรือบล็อกที่ได้รับการปกป้องจากการรบกวนจากเธรดอื่นๆ ที่ใช้ทรัพยากรร่วมกัน ซึ่งระบุโดยใช้คีย์เวิร์ด `synchronized`
- วิธีการใดๆ ที่ถูกประกาศเป็นแบบซิงโครไนซ์ จะเรียกว่าวิธีการซิงโครไนซ์
- In Javaการล็อควิธีการแบบซิงโครไนซ์จะเข้าถึงได้ที่วิธีการ ในขณะที่การล็อคบล็อกแบบซิงโครไนซ์จะเข้าถึงได้ที่วัตถุ
- ในการซิงโครไนซ์แบบคงที่ การล็อคการเข้าถึงจะอยู่ที่คลาส ไม่ใช่อยู่ที่วัตถุและวิธีการ
- วัตถุประสงค์หลักของการซิงโครไนซ์ใน Java คือการป้องกันข้อมูลที่ไม่สอดคล้องกันโดยการป้องกันการรบกวนของเธรด
- ข้อเสียเปรียบที่ใหญ่ที่สุดของวิธีนี้คือกระบวนการทั้งหมดถูกปล่อยให้รอ ดังนั้นกระบวนการสุดท้ายในคิวต้องรอจนกว่ากระบวนการอื่นๆ ทั้งหมดจะเสร็จสมบูรณ์