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 คือการป้องกันข้อมูลที่ไม่สอดคล้องกันโดยการป้องกันการรบกวนของเธรด
  • ข้อเสียเปรียบที่ใหญ่ที่สุดของวิธีนี้คือกระบวนการทั้งหมดถูกปล่อยให้รอ ดังนั้นกระบวนการสุดท้ายในคิวต้องรอจนกว่ากระบวนการอื่นๆ ทั้งหมดจะเสร็จสมบูรณ์