"Hello, Amigo! Semalam kita telah membincangkan faedah dan kemudahan multithreading. Kini tiba masanya untuk melihat keburukan. Dan, malangnya, mereka tidak kecil."

Sebelum ini, kami melihat program sebagai satu set objek yang memanggil kaedah masing-masing. Sekarang semuanya menjadi lebih rumit. Program lebih seperti satu set objek yang mempunyai beberapa "robot kecil" (benang) merangkak melaluinya dan melaksanakan arahan yang terkandung dalam kaedah.

Tafsiran baharu ini tidak membatalkan yang pertama. Mereka masih objek, dan mereka masih memanggil kaedah masing-masing. Tetapi kita harus ingat bahawa terdapat beberapa utas, dan setiap utas melakukan tugas atau tugasnya sendiri.

Sesuatu program menjadi lebih rumit. Benang yang berbeza mengubah keadaan objek yang berbeza berdasarkan tugas yang mereka lakukan. Dan mereka boleh memijak jari kaki masing-masing.

Tetapi perkara yang paling teruk berlaku jauh di dalam mesin Java. Seperti yang telah saya katakan, keselarasan jelas benang dicapai oleh fakta bahawa pemproses sentiasa beralih dari satu benang ke yang lain. Ia bertukar kepada benang, berfungsi selama 10 milisaat, beralih ke urutan seterusnya, berfungsi selama 10 milisaat dan seterusnya. Dan di sinilah masalahnya: suis ini boleh berlaku pada saat yang paling tidak sesuai. Pertimbangkan contoh ini:

Kod utas pertama Kod utas kedua
System.out.print ("Nick is");
System.out.print ("");
System.out.print ("15");
System.out.print ("");
System.out.print ("years old");
System.out.println ();
System.out.print ("Lena is");
System.out.print ("");
System.out.print ("21");
System.out.print ("");
System.out.print ("years old");
System.out.println ();
Apa yang kami harapkan akan dipaparkan
Nick berumur 15 tahun
Lena berumur 21 tahun
Pelaksanaan kod sebenar Kod utas pertama Kod utas kedua
System.out.print ("Nick is");
System.out.print ("Lena is");
System.out.print (" ");
System.out.print (" ");
System.out.print ("15");
System.out.print ("21");
System.out.print (" ");
System.out.print (" ");
System.out.print ("years old");
System.out.println ();
System.out.print ("years old");
System.out.println ();
System.out.print ("Nick is");
//other thread is running
//other thread is running
System.out.print (" ");
System.out.print ("15");
//other thread is running
//other thread is running
System.out.print (" ");
System.out.print ("years old");
System.out.println ();
//other thread is running
//other thread is running
//other thread is running
System.out.print ("Lena is");
System.out.print (" ");
//other thread is running
//other thread is running
System.out.print ("21");
System.out.print (" ");
//other thread is running
//other thread is running
//other thread is running
System.out.print ("years old");
System.out.println ();
Apa yang dipaparkan sebenarnya
Nick ialah  Lena   berumur 15  21  tahun

Dan inilah contoh lain:

Kod Penerangan
class MyClass
{
private String name1 = "Ally";
private String name2 = "Lena";
public void swap()
{
String s = name1;
name1 = name2;
name2 = s;
}
}
Kaedah swap swapnilai-nilai name1dan name2pembolehubah.

Apakah yang mungkin berlaku jika ia dipanggil daripada dua utas pada masa yang sama?

Pelaksanaan kod sebenar Kod utas pertama Kod utas kedua
String s1 = name1; //Ally
name1 = name2; //Lena
String s2 = name1; //Lena(!)
name1 = name2; //Lena
name2 = s1; //Ally
name2 = s2; //Lena
String s1 = name1;
name1 = name2;
//other thread is running
//other thread is running
name2 = s1;
//other thread is running
//other thread is running
//other thread is running
String s2 = name1;
name1 = name2;
//other thread is running
name2 = s2;
Garisan bawah
Kedua-dua pembolehubah mempunyai nilai «Lena».
Objek «Ally» tidak berjaya. Ia hilang.

"Siapa sangka kesilapan seperti ini boleh berlaku dengan operasi tugasan yang begitu mudah?!"

"Ya, masalah ini ada penyelesaiannya. Tetapi kita akan bercakap tentang ini sedikit kemudian - tekak saya kering."