"Bună, Amigo! Ieri am discutat despre beneficiile și avantajele multithreadingului. Acum este timpul să ne uităm la dezavantaje. Și, din păcate, nu sunt mici."

Anterior, am privit un program ca pe un set de obiecte care își numesc metodele unul altuia. Acum totul devine puțin mai complicat. Un program seamănă mai mult cu un set de obiecte care are mai mulți „roboți mici” (fire) care se târăsc prin el și execută comenzile conținute în metode.

Această nouă interpretare nu o anulează pe prima. Sunt încă obiecte și încă își numesc metode unul altuia. Dar trebuie să ne amintim că există mai multe fire și fiecare thread își face treaba sau sarcina.

Un program devine din ce în ce mai complicat. Diferite fire de execuție schimbă starea diferitelor obiecte în funcție de sarcinile pe care le îndeplinesc. Și se pot călca unul pe altul.

Dar cele mai rele lucruri se întâmplă adânc în interiorul mașinii Java. După cum am spus deja, aparenta simultaneitate a firelor de execuție se realizează prin faptul că procesorul trece constant de la un thread la altul. Trece la un fir, funcționează timp de 10 milisecunde, trece la următorul fir, funcționează timp de 10 milisecunde și așa mai departe. Și aici constă problema: aceste comutări pot apărea în cele mai inoportune momente. Luați în considerare acest exemplu:

Codul primului fir Codul celui de-al doilea fir
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 ();
Ce ne așteptam să fie afișat
Nick are 15 ani
Lena are 21 de ani
Execuția reală a codului Codul primului fir Codul celui de-al doilea fir
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 ();
Ce este de fapt afișat
Nick este  Lena are   15  21  de ani

Și iată un alt exemplu:

Cod Descriere
class MyClass
{
private String name1 = "Ally";
private String name2 = "Lena";
public void swap()
{
String s = name1;
name1 = name2;
name2 = s;
}
}
Metoda de schimb swapvalorile variabilelor name1și name2.

Ce s-ar putea întâmpla dacă este apelat din două fire în același timp?

Execuția reală a codului Codul primului fir Codul celui de-al doilea fir
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;
Linia de jos
Ambele variabile au valoarea «Lena».
Obiectul «Ally» nu a reușit. S-a pierdut.

„Cine ar fi ghicit că astfel de erori sunt posibile cu o operație de atribuire atât de simplă?!”

"Da, această problemă are o soluție. Dar despre asta vom vorbi puțin mai târziu - gâtul meu este uscat."