CodeGym /Java Blog /Acak /Sinkronisasi utas. Operator yang disinkronkan
John Squirrels
Level 41
San Francisco

Sinkronisasi utas. Operator yang disinkronkan

Dipublikasikan di grup Acak
Hai! Hari ini kami akan terus mempertimbangkan fitur pemrograman multithread dan berbicara tentang sinkronisasi utas. Sinkronisasi utas.  Operator yang disinkronkan - 1

Apa itu sinkronisasi di Jawa?

Di luar domain pemrograman, ini menyiratkan pengaturan yang memungkinkan dua perangkat atau program bekerja bersama. Misalnya, ponsel cerdas dan komputer dapat disinkronkan dengan akun Google, dan akun situs web dapat disinkronkan dengan akun jejaring sosial sehingga Anda dapat menggunakannya untuk masuk. Sinkronisasi utas memiliki arti yang serupa: ini adalah pengaturan di mana utas berinteraksi satu sama lain. Dalam pelajaran sebelumnya, utas kami hidup dan bekerja secara terpisah satu sama lain. Satu melakukan perhitungan, yang kedua tidur, dan yang ketiga menampilkan sesuatu di konsol, tetapi tidak berinteraksi. Dalam program nyata, situasi seperti itu jarang terjadi. Beberapa utas dapat secara aktif bekerja dengan dan memodifikasi kumpulan data yang sama. Ini menciptakan masalah. Bayangkan beberapa utas menulis teks ke tempat yang sama, misalnya, ke file teks atau konsol. Dalam hal ini, file atau konsol menjadi sumber daya bersama. Utas tidak menyadari keberadaan satu sama lain, jadi mereka hanya menulis semua yang mereka bisa dalam waktu yang ditentukan oleh penjadwal utas. Dalam pelajaran baru-baru ini, kami melihat contoh ke mana hal ini mengarah. Mari kita mengingatnya sekarang: Sinkronisasi utas.  Operator yang disinkronkan - 2Alasannya terletak pada fakta bahwa utas bekerja dengan sumber daya bersama (konsol) tanpa mengoordinasikan tindakan mereka satu sama lain. Jika penjadwal utas mengalokasikan waktu ke Utas-1, maka ia langsung menulis semuanya ke konsol. Apa yang telah atau belum berhasil ditulis oleh utas lain tidak masalah. Hasilnya, seperti yang Anda lihat, menyedihkan. Itu sebabnya mereka memperkenalkan konsep khusus, mutex (pengecualian bersama) , untuk pemrograman multithreaded. Tujuan mutexadalah menyediakan mekanisme sehingga hanya satu utas yang memiliki akses ke suatu objek pada waktu tertentu. Jika Thread-1 memperoleh mutex objek A, thread lain tidak akan dapat mengakses dan memodifikasi objek. Utas lainnya harus menunggu hingga mutex objek A dilepaskan. Inilah contoh dari kehidupan: bayangkan Anda dan 10 orang asing lainnya berpartisipasi dalam latihan. Secara bergiliran, Anda perlu mengungkapkan ide-ide Anda dan mendiskusikan sesuatu. Tetapi karena Anda bertemu untuk pertama kalinya, agar tidak terus-menerus mengganggu satu sama lain dan menjadi marah, Anda menggunakan 'bola berbicara': hanya orang yang memiliki bola yang dapat berbicara. Dengan cara ini Anda akhirnya memiliki diskusi yang baik dan bermanfaat. Pada dasarnya, bola adalah mutex. Jika mutex objek ada di tangan satu utas, utas lainnya tidak dapat bekerja dengan objek tersebut.Objectkelas, yang berarti bahwa setiap objek di Jawa memiliki satu.

Cara kerja operator yang disinkronkan

Mari berkenalan dengan kata kunci baru: disinkronkan . Ini digunakan untuk menandai blok kode tertentu. Jika blok kode ditandai dengan synchronizedkata kunci, maka blok itu hanya dapat dieksekusi oleh satu utas dalam satu waktu. Sinkronisasi dapat diimplementasikan dengan berbagai cara. Misalnya, dengan mendeklarasikan seluruh metode untuk disinkronkan:

public synchronized void doSomething() {

   // ...Method logic
}
Atau tulis blok kode tempat sinkronisasi dilakukan menggunakan beberapa objek:

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...Some logic available simultaneously to all threads

       synchronized (obj) {

           // Logic available to just one thread at a time
       }
   }
}
Artinya sederhana. Jika satu utas masuk ke dalam blok kode yang ditandai dengan synchronizedkata kunci, ia langsung menangkap mutex objek, dan semua utas lain yang mencoba memasuki blok atau metode yang sama terpaksa menunggu hingga utas sebelumnya menyelesaikan pekerjaannya dan melepaskan monitor. Sinkronisasi utas.  Operator yang disinkronkan - 3Omong-omong! Selama kursus, Anda telah melihat contoh synchronized, tetapi terlihat berbeda:

public void swap()
{
   synchronized (this)
   {
       // ...Method logic
   }
}
Topiknya baru untuk Anda. Dan tentunya akan ada kebingungan dengan sintaksnya. Jadi, segera hafalkan agar tidak bingung nantinya karena perbedaan cara penulisannya. Kedua cara penulisan ini memiliki arti yang sama:

public void swap() {

   synchronized (this)
   {
       // ...Method logic
   }
}


public synchronized void swap() {

   }
}
Dalam kasus pertama, Anda membuat blok kode yang disinkronkan segera setelah memasukkan metode. Itu disinkronkan oleh thisobjek, yaitu objek saat ini. Dan pada contoh kedua, Anda menerapkan synchronizedkata kunci ke seluruh metode. Ini membuatnya tidak perlu secara eksplisit menunjukkan objek yang digunakan untuk sinkronisasi. Karena seluruh metode ditandai dengan kata kunci, metode tersebut akan secara otomatis disinkronkan untuk semua instance kelas. Kami tidak akan terjun ke diskusi tentang cara mana yang lebih baik. Untuk saat ini, pilih cara mana yang paling Anda sukai :) Hal utama yang harus diingat: Anda dapat mendeklarasikan metode yang disinkronkan hanya jika semua logikanya dijalankan oleh satu utas pada satu waktu. Misalnya, salah jika doSomething()metode berikut disinkronkan:

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...Some logic available simultaneously to all threads

       synchronized (obj) {

           // Logic available to just one thread at a time
       }
   }
}
Seperti yang Anda lihat, bagian dari metode berisi logika yang tidak memerlukan sinkronisasi. Kode itu dapat dijalankan oleh banyak utas pada saat yang sama, dan semua tempat penting dipisahkan dalam synchronizedblok terpisah. Dan satu hal lagi. Mari kita cermati contoh kita dari pelajaran dengan pertukaran nama:

public void swap()
{
   synchronized (this)
   {
       // ...Method logic
   }
}
Catatan: sinkronisasi dilakukan menggunakanthis. Artinya, menggunakanMyClassobjek tertentu. Misalkan kita memiliki 2 utas (Thread-1danThread-2) dan hanya satuMyClass myClassobjek. Dalam hal ini, jikaThread-1memanggilmyClass.swap()metode, mutex objek akan sibuk, dan ketika mencoba memanggilmyClass.swap()metodeThread-2akan macet sambil menunggu mutex dilepaskan. Jika kita akan memiliki 2 utas dan 2MyClassobjek (myClass1danmyClass2), utas kita dapat dengan mudah menjalankan metode yang disinkronkan secara bersamaan pada objek yang berbeda. Utas pertama menjalankan ini:

myClass1.swap();
Yang kedua mengeksekusi ini:

myClass2.swap();
Dalam hal ini, synchronizedkata kunci di dalam swap()metode tidak akan memengaruhi pengoperasian program, karena sinkronisasi dilakukan menggunakan objek tertentu. Dan dalam kasus terakhir, kami memiliki 2 objek. Dengan demikian, utas tidak menimbulkan masalah satu sama lain. Lagi pula, dua objek memiliki 2 mutex yang berbeda, dan memperoleh satu tidak tergantung pada memperoleh yang lain .

Fitur khusus sinkronisasi dalam metode statis

Tetapi bagaimana jika Anda perlu menyinkronkan metode statis ?

class MyClass {
   private static String name1 = "Ally";
   private static String name2 = "Lena";

   public static synchronized void swap() {
       String s = name1;
       name1 = name2;
       name2 = s;
   }

}
Tidak jelas peran apa yang akan dimainkan mutex di sini. Bagaimanapun, kami telah menentukan bahwa setiap objek memiliki mutex. Tapi masalahnya adalah kita tidak memerlukan objek untuk memanggil metode MyClass.swap(): metode ini statis! Terus gimana? :/ Sebenarnya tidak ada masalah di sini. Pembuat Java mengurus semuanya :) Jika metode yang berisi logika konkuren kritis bersifat statis, maka sinkronisasi dilakukan di tingkat kelas. Untuk kejelasan yang lebih besar, kita dapat menulis ulang kode di atas sebagai berikut:

class MyClass {
   private static String name1 = "Ally";
   private static String name2 = "Lena";

   public static void swap() {

       synchronized (MyClass.class) {
           String s = name1;
           name1 = name2;
           name2 = s;
       }
   }

}
Pada prinsipnya, Anda dapat memikirkannya sendiri: Karena tidak ada objek, mekanisme sinkronisasi entah bagaimana harus dimasukkan ke dalam kelas itu sendiri. Dan begitulah: kita bisa menggunakan kelas untuk menyinkronkan.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION