"Hello, Amigo! Yesterday we discussed the benefits and conveniences of multithreading. Now it's time to look at the disadvantages. And, unfortunately, they are not small."

Previously, we looked at a program as a set of objects that call each other's methods. Now everything gets a little more complicated. A program is more like a set of objects that has several "small robots" (threads) crawling through it and executing the commands contained in the methods.

This new interpretation doesn't cancel the first. They are still objects, and they still call each other's methods. But we have to remember that there are several threads, and each thread does its own job or task.

A program is becoming more complicated. Different threads change the state of different objects based on the tasks they perform. And they can step on each other's toes.

But the worst stuff happens deep inside the Java machine. As I've said already, the apparent simultaneity of threads is achieved by the fact that the processor constantly switches from one thread to another. It switches to a thread, works for 10 milliseconds, switches to the next thread, works for 10 milliseconds, and so on. And herein lies the problem: these switches can occur at the most inopportune moments. Consider this example:

Code of the first thread Code of the second thread
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 ();
What we expected to be displayed
Nick is 15 years old
Lena is 21 years old
Actual code execution Code of the first thread Code of the second thread
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 ();
What is actually displayed
Nick is Lena is  15 21 years old
years old

And here's another example:

Code Description
class MyClass
{
private String name1 = "Ally";
private String name2 = "Lena";
public void swap()
{
String s = name1;
name1 = name2;
name2 = s;
}
}
The swap method swap the values of the name1 and name2 variables.

What might happen if it is called from two threads at the same time?

Actual code execution Code of the first thread Code of the second thread
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;
The bottom line
Both variables have the value «Lena».
The «Ally» object didn't make it. It's lost.

"Who would have guessed that errors like this are possible with such a simple assignment operation?!"

"Yes, this problem has a solution. But we'll talk about this a little later - my throat is dry."