Synckronisasi di Java

Apa itu Synckronisasi di Java?

In Java, sinkronisasi mengacu pada kemampuan untuk mengendalikan akses beberapa thread ke sumber daya bersama apa pun. Ini adalah opsi ideal jika kita ingin mengizinkan hanya satu thread untuk mengakses sumber daya bersama.

Pendekatan eksekusi ini biasanya disebut sebagai pemrograman `asynchronous`. Ada juga thread pada prosesor ini, yang merupakan proses ringan yang dapat mengeksekusi instruksi secara bersamaan.

Jenis dari Synchronisasi

Ada dua jenis metode sinkronisasi dalam Java:

1) Sinkronisasi proses

2) Sinkronisasi utas.

Mari kita pelajari Thread dan Sinkronisasi proses secara terperinci.

Sinkronisasi proses: Ini mengelola sinkronisasi antar program. Misalnya, program seperti `Microsoft Word` dan `Acrobat reader` dijalankan sebagai proses individual.

Sinkronisasi utas: Eksekusi sumber daya penting secara bersamaan oleh dua atau lebih Thread disebut Thread Synckronisasi. Anda dapat dikelompokkan lebih lanjut ke komunikasi saling eksklusif` dan antar-utas.

Apa itu Kunci Java?

Kunci masuk Java dibangun di sekitar entitas internal yang dikenal sebagai monitor atau kunci. Semua objek memiliki kunci yang terkait dengannya. Jadi, thread yang memerlukan akses konsisten ke bidang objek harus memperoleh kunci objek sebelum mengaksesnya, dan melepaskan kunci tersebut ketika pekerjaan selesai. Hal ini memastikan bahwa hanya satu thread yang mengakses data bersama pada satu waktu.

Program multithreaded dengan sinkronisasi

Sebuah program multithread adalah metode atau blok yang dilindungi dari gangguan dari thread lain yang berbagi sumber daya yang sama yang ditunjukkan menggunakan kata kunci `synchronized`.

Menggunakan metode sinkronisasi

Metode apa pun yang dideklarasikan sebagai metode tersinkronisasi dikenal sebagai Metode Tersinkronisasi. Metode ini juga digunakan untuk mengunci objek untuk sumber daya bersama apa pun. Jadi, saat utas memanggil metode tersinkronisasi, utas tersebut secara otomatis mengambil alih kunci untuk objek tersebut dan melepaskannya saat utas telah menyelesaikan tugasnya.

Catatan: Kata kunci sinkronisasi tidak dapat digunakan dengan kelas dan variabel. Hanya metode dan blok yang dapat digunakan dengan kata kunci tersebut.

Mengapa menggunakan SyncMetode yang dikronisasikan?

  • Ini digunakan untuk mengunci objek untuk sumber daya bersama apa pun.
  • Objek tersebut mendapat kunci setiap kali metode yang disinkronkan dipanggil.
  • Kunci tidak akan terlepas sampai benang menyelesaikan fungsinya

sintaks:

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();
    }
}

Penjelasan Kode:

Jalankan contoh ini dan amati bahwa thread `0` mendapatkan kunci objek `mathService` terlebih dahulu dan menggunakan kunci ini secara eksklusif hingga selesai dieksekusi. Thread `0` dan `1` tidak disisipkan dalam kode ini. Outputnya seperti gambar di bawah ini.

Keluaran:

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

Menggunakan blok yang disinkronkan

Mari kita asumsikan bahwa Anda tidak ingin menyinkronkan seluruh metode. Sebaliknya, Anda ingin menyinkronkan beberapa baris kode. Pada saat itu, Syncblok yang dikronisasi membantu menyinkronkan yang dipilih Java kode. SyncKunci metode yang dikronisasikan diakses pada metode, sedangkan kunci blok yang disinkronisasikan diakses pada objek.

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();
    }
}

Penjelasan Kode:

Setelah menjalankan kode ini, Anda akan melihat bahwa kode tersebut berfungsi tanpa gangguan apa pun. Dalam metode sinkronisasi, kunci diterapkan oleh metode, tetapi dalam blok sinkronisasi, kunci diterapkan oleh objek. Pastikan outputnya seperti yang ditunjukkan di bawah ini.

Keluaran:

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

Penjelasan kode:

Saat Anda menjalankan kode ini, Anda akan melihat bahwa kode tersebut bekerja tanpa gangguan, yang merupakan hal yang kami harapkan. Dalam metode sinkronisasi, kunci diterapkan oleh metode, tetapi dalam metode blok sinkronisasi, kunci diterapkan oleh objek.

Menggunakan sinkronisasi statis

In Java sinkronisasi, jika ada lebih dari satu objek, dua utas dapat memperoleh kunci dan memasuki blok atau blok yang disinkronkan, dengan kunci terpisah untuk setiap objek. Untuk menghindari hal ini, sinkronisasi statis dapat digunakan. Synckata kunci yang dironisasi akan digunakan sebelum metode statis.

Catatan: Dalam sinkronisasi statis, akses terkunci pada kelas, bukan pada objek dan metode.

Kode untuk menunjukkan masalah penguncian beberapa objek

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();
    }
}

Penjelasan kode:

Saat kami membuat instance lain dari `MathService`, kami menimbulkan interferensi pada thread karena thread tersebut akan disisipkan dengan dua objek. Perhatikan bahwa thread `0` dan thread `2` disisipkan dengan dua objek, sedangkan thread `1` dan `3` disisipkan dengan dua objek.

Keluaran:

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

Kode yang sama menggunakan metode statis yang disinkronkan

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();
    }
}

Jalankan kode di atas dan perhatikan bahwa kami sekarang telah menghilangkan gangguan thread. Output dari kode ditunjukkan di bawah ini.

Keluaran:

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

Keuntungan menggunakan sinkronisasi

Berikut keuntungan bekerja dengan aplikasi bersamaan:

  • Tujuan utama sinkronisasi dalam Java adalah untuk mencegah data yang tidak konsisten dengan mencegah gangguan thread.
  • Kata kunci sinkronisasi dalam Java menyediakan penguncian, yang memastikan akses saling eksklusif ke sumber daya bersama dan mencegah perlombaan data.
  • Ini juga mencegah penyusunan ulang pernyataan kode oleh penyusun, yang dapat menyebabkan masalah bersamaan yang tidak kentara jika kita tidak menggunakan kata kunci yang mudah berubah atau tersinkronisasi.
  • Synckata kunci hronized membaca data dari memori utama daripada cache dan ketika kuncinya dilepaskan.
  • Ia juga membuang operasi penulisan dari memori utama, menghilangkan kesalahan ketidakkonsistenan memori.

Kekurangan dari SyncMekanisme Kronisasi

SyncMekanisme hronisasi memiliki kinerja yang buruk.

Misalnya

  • Asumsikan ada lima proses, A1, A2, A3, A4, dan A5.
  • Mereka menunggu sumber daya bersama untuk mengakses satu thread pada satu waktu.
  • Semua proses dibiarkan menunggu, jadi yang terakhir dalam antrian harus menunggu hingga semua proses lainnya selesai.

Kesimpulan

  • Synchronisasi mengacu pada kemampuan untuk mengontrol akses beberapa thread ke sumber daya bersama.
  • Java memiliki dua jenis metode sinkronisasi: 1) Sinkronisasi proses dan 2) Sinkronisasi utas.
  • Kunci masuk Java dibangun di sekitar entitas internal yang dikenal sebagai monitor atau kunci.
  • Program Multithreaded adalah metode atau blok yang dilindungi dari gangguan dari thread lain yang berbagi sumber daya yang sama yang ditunjukkan menggunakan kata kunci `synchronized`.
  • Metode apa pun yang dideklarasikan sebagai tersinkronisasi dikenal sebagai metode tersinkronisasi.
  • In Java, kunci metode tersinkronisasi diakses pada metode, sedangkan kunci blok tersinkronisasi diakses pada objek.
  • Dalam sinkronisasi statis, akses terkunci pada kelas, bukan pada objek dan metode.
  • Tujuan utama sinkronisasi dalam Java adalah untuk mencegah data yang tidak konsisten dengan mencegah gangguan thread.
  • Kelemahan terbesar dari metode ini adalah semua proses dibiarkan menunggu, sehingga antrian terakhir harus menunggu hingga semua proses lainnya selesai.