In the class below, is the method getIt()
thread safe and why?
public class X {
private long myVar;
public void setIt(long var){
myVar = var;
}
public long getIt() {
return myVar;
}
}
Thread Synchronization is a process of allowing only one thread to use the object when multiple threads are trying to use the particular object at the same time. To achieve this Thread Synchronization we have to use a java keyword or modifier called “synchronized”.
Synchronization in Java is the capability to control the access of multiple threads to any shared resource. Java Synchronization is better option where we want to allow only one thread to access the shared resource.
This synchronization is implemented in Java with a concept called monitors. Only one thread can own a monitor at a given time. When a thread acquires a lock, it is said to have entered the monitor. All other threads attempting to enter the locked monitor will be suspended until the first thread exits the monitor.
In Java, each object has a lock or a monitor. This lock can be accessed by a thread. At a time only one thread can acquire this monitor or lock. Java programming language provides a keyword Synchronized' that allows us to synchronize the threads by making a block or method as Synchronized.
It is not thread-safe. Variables of type long
and double
in Java are treated as two separate 32-bit variables. One thread could be writing and have written half the value when another thread reads both halves. In this situation, the reader would see a value that was never supposed to exist.
To make this thread-safe you can either declare myVar
as volatile
(Java 1.5 or later) or make both setIt
and getIt
synchronized
.
Note that even if myVar
was a 32-bit int
you could still run into threading issues where one thread could be reading an out of date value that another thread has changed. This could occur because the value has been cached by the CPU. To resolve this, you again need to declare myVar
as volatile
(Java 1.5 or later) or make both setIt
and getIt
synchronized
.
It's also worth noting that if you are using the result of getIt
in a subsequent setIt
call, e.g. x.setIt(x.getIt() * 2)
, then you probably want to synchronize
across both calls:
synchronized(x)
{
x.setIt(x.getIt() * 2);
}
Without the extra synchronization, another thread could change the value in between the getIt
and setIt
calls causing the other thread's value to be lost.
This is not thread-safe. Even if your platform guarantees atomic writes of long
, the lack of synchronized
makes it possible that one thread calls setIt()
and even after this call has finished it is possible that another thread can call getIt()
and this call could return the old value of myVar
.
The synchronized
keyword does more than an exclusive access of one thread to a block or a method. It also guarantees that the second thread is informed about a change of a variable.
So you either have to mark both methods as synchronized
or mark the member myVar
as volatile
.
There's a very good explanation about synchronization here:
Atomic actions cannot be interleaved, so they can be used without fear of thread interference. However, this does not eliminate all need to synchronize atomic actions, because memory consistency errors are still possible. Using volatile variables reduces the risk of memory consistency errors, because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable. This means that changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With