CodeGym /Courses /Java Core /Threads aren't independent! Synchronized!

Threads aren't independent! Synchronized!

Java Core
Level 7 , Lesson 3
Available

"Hello, Amigo! We have a panacea—a cure for all diseases. As we've already seen, uncontrolled thread switching is a problem."

"Why can't the threads themselves decide when to switch to the next thread? Do everything they need to do and then signal, «I'm done!»?"

"Allowing threads themselves to control switching would be an even bigger problem. Suppose you have some poorly written code, and the thread never surrenders the CPU. Back in the day, this is how it worked. And it was quite a nightmare."

"Okay. So what's the solution?"

"Blocking other threads. This is how it works."

It became clear that threads interfere with each other when they try to use shared objects and/or resources. Just as we saw in the example with console output: there's one console and all the threads output to it. It's messy.

So a special object was invented: the mutex. It's like a sign on a bathroom door that says «available/occupied». It has two states: the object is available or occupied. These states are also called «locked» and «unlocked».

When a thread needs an object shared with other threads, it checks the mutex associated with the object. If the mutex is unlocked, then the thread locks it (marks it as «occupied») and starts using the shared resource. After the thread has done its business, the mutex is unlocked (marked as «available»).

If the thread wants to use the object and the mutex is locked, then the thread sleep while it waits. When the mutex is finally unlocked by the occupying thread, our thread will immediately lock it and start running. The analogy with a bathroom door sign is perfect.

"So how do I work with a mutex? Do I need to create special objects?"

"It's a lot simpler than that. Java's creators built this mutex into the Object class. So you don't even have to create it. It's part of every object. Here's how it all works:"

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

public void swap()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}
}
The swap method swaps 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
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;
The bottom line
The values of the variables were swapped twice, returning to their original places.

Pay attention to the keyword synchronized.

"Yeah, what does it mean?"

"When a thread enters a block of code marked as synchronized, the Java machine immediately locks the mutex of the object indicated in parentheses after the word synchronized. No other thread can enter this block until our thread leaves it. As soon as our thread leaves the block marked synchronized, the mutex is immediately and automatically unlocked and will be available to be acquired by another thread."

If the mutex is occupied, then our thread will stand still and wait for it to free up.

"So simple and so elegant. That's a beautiful solution."

"Yes. But what do you think will happen in this case?"

Code Description
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;
}
}
}
The swap and swap2 methods share the same mutex (the this object).

What happens if one thread calls the swap method and another thread calls the swap2 method?

"Since the mutex is the same, the second thread will have to wait until the first thread leaves the synchronized block. So there won't be any problems with simultaneous access."

"Well done, Amigo! That's the correct answer!"

Now I'd like to point out that synchronized can be used to mark not only blocks of code, but also methods. Here's what that means:

Code What really happens
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;
}
}
Comments (12)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Evgeniia Shabaeva Level 42, Budapest, Hungary
8 August 2024
Wow!
Krig Raseri Level 38, Dallas, United States
15 February 2023
Mutex is dope name. The lands were peaceful until the Mutex attacked.
moseka Level 23, Nairobi, Kenya
1 July 2020
This video might help https://www.youtube.com/watch?v=RH7G-N2pa8M
Олег Байбула Level 32, Ukraine Expert
3 February 2023
It didn't. I can't get his accent.)))
HaeWon Chung Level 17, Boston, United States
25 June 2020
I'm a little bit confused for the first example. How does other thread runs between

name1 = name2;
and

name2 = s1;
I thought second thread would run only after name2 = s1;
Gellert Varga Level 23, Szekesfehervar, Hungary
7 May 2021
In the "Actual code execution" field, you can see that the execution is now in the expected order. Thus, in my opinion it is quite certain that the note "other thread running" in the "Code of the first thread" field can not signify the second thread, because that thread cannot enter this method until the first thread is done with it. I suppose if you have a long synchronized method, the JVM will not execute it all at once if there also are other running threads in the program somewhere else. It works a bit in the synchronized method, then it works a little somewhere else in other threads, then returns to the synchronized method and finishes its work. And when thread 1 is completely finished its work inside the synchronized method, then thread 2 may enter and start its own work. All this is just an assumption.
Zserbo Level 22, Budapest, Hungary
8 May 2020
I think there is a typo: It became clear that threads interfere with each other when they try to used shared objects and/or resources
Alex Vypirailenko Level 41, USA
9 May 2020
Thanks. We will fix it soon.
Ivaylo Trifonov Level 26, Madrid, Spain
27 July 2019
And what about if 3 or more threads want access to the same object? There is some kind of priority check? Like, the first thread who tries to interact with an "occupied" object gets priority of 10, the next one 9, and so on?
Jen P Level 26
4 August 2019
would like to know too
Kingpvz Level 31, Slovakia
11 March 2025
i think in this case it already depends on where and when you've written the very line of code that does this, the sooner = the higher the priority
Ewerton Level 30, Belo Horizonte, Brasil
2 July 2019
Cool