"Halo, Amigo! Kami memiliki obat mujarab—obat untuk semua penyakit. Seperti yang telah kita lihat, pergantian benang yang tidak terkendali adalah sebuah masalah."

"Mengapa utas itu sendiri tidak dapat memutuskan kapan harus beralih ke utas berikutnya? Lakukan semua yang perlu mereka lakukan dan kemudian beri tanda, «Saya selesai!»?"

"Mengizinkan utas itu sendiri untuk mengontrol peralihan akan menjadi masalah yang lebih besar. Misalkan Anda memiliki beberapa kode yang ditulis dengan buruk, dan utas tidak pernah menyerahkan CPU. Dulu, begitulah cara kerjanya. Dan itu benar-benar mimpi buruk."

"Oke. Jadi apa solusinya?"

" Memblokir utas lain.  Begini cara kerjanya."

Menjadi jelas bahwa utas saling mengganggu ketika mereka mencoba menggunakan objek dan/atau sumber daya bersama . Seperti yang kita lihat pada contoh dengan keluaran konsol: ada satu konsol dan semua keluaran utas ke sana. Ini berantakan.

Jadi objek khusus ditemukan: mutex . Itu seperti tanda di pintu kamar mandi yang bertuliskan «tersedia / ditempati» . Ini memiliki dua status: objek tersedia atau ditempati . Status ini juga disebut «terkunci» dan «tidak terkunci».

Ketika sebuah utas membutuhkan objek yang dibagikan dengan utas lainnya, ia memeriksa mutex yang terkait dengan objek tersebut. Jika mutex tidak terkunci, maka utas menguncinya (menandai sebagai «ditempati») dan mulai menggunakan sumber daya bersama. Setelah utas menyelesaikan tugasnya, mutex dibuka kuncinya (ditandai sebagai «tersedia»).

Jika utas ingin menggunakan objek dan mutex dikunci, utas akan tidur sambil menunggu. Saat mutex akhirnya dibuka oleh utas yang menempati, utas kami akan segera menguncinya dan mulai berjalan. Analogi dengan tanda pintu kamar mandi sangat cocok.

"Jadi, bagaimana cara saya bekerja dengan mutex? Apakah saya perlu membuat objek khusus?"

"Jauh lebih sederhana dari itu. Pencipta Java membangun mutex ini ke dalam kelas Object. Jadi Anda bahkan tidak perlu membuatnya. Itu adalah bagian dari setiap objek. Begini cara kerjanya:"

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

public void swap()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}
}
Metode swap menukar nilai variabel name1 dan name2.

Apa yang mungkin terjadi jika dipanggil dari dua utas sekaligus?

Eksekusi kode aktual Kode thread pertama Kode thread kedua
String s1 = name1; //Ally
name1 = name2; //Lena
name2 = s1; //Ally

String s2 = name1; //Lena
name1 = name2; //Ally
name2 = s2; //Lena
String s1 = name1;
name1 = name2;
//other thread is running
name2 = s1;
//the thread waits until the mutex is unlocked

String s2 = name1;
name1 = name2;
//other thread is running
//other thread is running
name2 = s2;
Garis bawah
Nilai variabel ditukar dua kali, kembali ke tempat asalnya.

Perhatikan kata kunci  yang disinkronkan .

"Ya, apa artinya?"

"Ketika sebuah utas memasuki blok kode yang ditandai sebagai disinkronkan, mesin Java segera mengunci mutex objek yang ditunjukkan dalam tanda kurung setelah kata disinkronkan. Tidak ada utas lain yang dapat memasuki blok ini sampai utas kami meninggalkannya. Segera setelah utas kami keluar blok ditandai disinkronkan, mutex segera dan secara otomatis dibuka dan akan tersedia untuk diperoleh oleh utas lain."

Jika mutex ditempati, maka utas kami akan diam dan menunggu hingga kosong.

"Sangat sederhana dan elegan. Itu solusi yang bagus."

"Ya. Tapi menurutmu apa yang akan terjadi dalam kasus ini?"

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

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

public void swap2()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}
}
Metode swap dan swap2 berbagi mutex yang sama ( objek this ).

Apa yang terjadi jika satu utas memanggil metode swap dan utas lainnya memanggil metode swap2?

"Karena mutexnya sama, utas kedua harus menunggu hingga utas pertama meninggalkan blok yang disinkronkan. Jadi tidak akan ada masalah dengan akses simultan."

"Bagus, Amigo! Itu jawaban yang benar!"

Sekarang saya ingin menunjukkan bahwa sinkronisasi dapat digunakan untuk menandai tidak hanya blok kode, tetapi juga metode. Inilah artinya:

Kode Apa yang sebenarnya terjadi
class MyClass
{
private static String name1 = "Ally";
private static String name2 = "Lena";

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

public static synchronized void swap2()
{
String s = name1;
name1 = name2;
name2 = s;
}
}
class MyClass
{
private static String name1 = "Ally";
private static String name2 = "Lena";

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

public static void swap2()
{
synchronized (MyClass.class)
{
String s = name1;
name1 = name2;
name2 = s;
}
}