Is this code not thread safe? - java

I was expecting this code to be thread safe. I ran it a few times, but got different results. However, if I uncomment the sleep(1000) part, it prints 10000 every time (at least from the results from my test runs).
So what's wrong? Could it be something to do with thread.join()?
public class Test implements Runnable{
private int x;
public synchronized void run(){
x++;
}
public static void main(String args[]){
Test test = new Test();
Thread thread = null;
for (int i = 0; i < 10000; i++) {
thread = new Thread(test);
try {
thread.join();
} catch (InterruptedException e) {}
thread.start();
}
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println(test.x);
}
}
edit: oops, my bad. I misunderstood how Thread#join functions. And synchronizing on run() method is a bad idea.

thread.join() should be called after thread.start().
join() means "block until the thread finishes". That only makes sense after the thread has started.
Presumably your Thread.sleep() call actually waits long enough for all the threads (that you effectively didn't join) to finish. Without it, the threads might not all have finished when you print out the value of x.

There are two problems here:
a race condition where the main thread finishes before all the worker threads.
a memory visibility issue where the main thread is not guaranteed to see the updated value of x.
Thread#join is implemented using Object#wait. The condition variable used is the alive flag on the Thread:
groovy:000> new Thread().isAlive()
===> false
Thread.join is checking the alive flag before the thread has started, so isAlive returns false and join returns before the thread can start. The counter still gets incremented eventually, but since the join doesn't happen for that thread then the main thread may be printing out the results for x before all the threads can execute.
Adding the sleep gives all the threads enough time to finish up that x is what you expect by the time that the main thread prints it out.
In addition to the race condition, there is a memory visibility issue since the main thread is accessing x directly and is not using the same lock as the other threads. You should add an accessor to your Runnable using the synchronized keyword:
public class Test implements Runnable{
private int x;
public synchronized void run(){
x++;
}
public synchronized int getX() {
return x;
}
and change the main method to use the accessor:
System.out.println(test.getX());
Memory visibility issues may not be apparent since they depend on how aggressive the JVM is about caching and optimizing. If your code runs against a different JVM implementation in production, and you don't adequately guard against these issues, you may see errors there that you can't reproduce locally on a PC.
Using AtomicInteger would simplify this code and allow solving the memory visibility problem while removing synchronization.

You don't add synchronized to the run method. Each thread gets its own.
You have to synchronize the mutable, shared data. In your case, that's the integer x. You can synchronize get/set or use AtomicInteger.

Related

Java code exits after some seconds due to concurrency

I am writing the same code on tutorial. But in tutorial the program never exits, my in my computer it exits after 4 seconds. Why?
tutorial with exact time where this code is shown: https://youtu.be/vzBw1LPupnA?t=169
public class Main {
private static boolean stopRequested;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(() -> {
int i = 0;
while (!stopRequested) {
i++;
System.out.println("i = " + i);
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
The reason that you are seeing different behavior on your machine and in the video is because the program has unspecified behavior. (Or to put it another way, it is not thread-safe.)
You have two threads accessing and updating a shared variable without taking the necessary steps that will guarantee that changes made by one thread are visible to the other. What happens in that case is not specified.
In some cases (e.g. on some platforms) the changes will be visible, either immediately or within a short time.
On others, the changes may never be visible.
In technical terms, there must be a happens-before relationship between the write by on thread and the subsequent read by the other thread. This can be provided by both threads synchronizing on the same mutex or lock, by using a volatile variable, and in other ways. But this code doesn't do any of those things, so there is no guarantee that the state change will be visible.
For more details, read about the Java Memory Model.
The above is sufficient to explain the difference, but there may be a more direct explanation.
In practice, something like a System.out.println can lead to changes in the visibility. Underneath the covers, the println call will typically result in synchronization on the output stream's buffers. That can result in a serendipitous happens-before that is sufficient to guarantee visibility. But this behavior is not specified, so you should not rely on it.
At any rate, adding trace statements can change the behavior of multi-threaded coded. And the fact that you (apparently) added them in your version is a second possible explanation for the difference.
The bottom line here is that a program with a memory visibility flaw is broken, but you may not be able to demonstrate that it is broken.
As the excellent Answer by Stephen C says, your code is not thread-safe.
Establishing an AtomicBoolean early on addresses the visibility problem explained in that other Answer. This class is a thread-safe wrapper around its payload boolean value.
The volatile keyword is another solution. But I find the Atomic… classes simpler and more obvious.
Also, in modern Java we rarely need to address the Thread class directly. Instead, use the Executors framework. Define your task as a Runnable or Callable, and submit to an executor service.
Something like this untested code.
public class Main {
private static final AtomicBoolean stopRequested = new AtomicBoolean( false ) ;
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
int i = 0;
while ( ! stopRequested.get() ) {
i++;
System.out.println("i = " + i);
TimeUnit.MILLISECONDS.sleep(100); // Don’t spin too fast.
}
};
ExecutorService es = Executors.newSingleThreadedExecutorService() ;
es.submit( task ) ;
TimeUnit.SECONDS.sleep(1);
stopRequested.set( true ) ;
TimeUnit.SECONDS.sleep(1);
// Shut down here executor service. Boilerplate taken from Javadoc.
es.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!es.awaitTermination(60, TimeUnit.SECONDS)) {
es.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!es.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Executor service did not terminate");
}
} catch (InterruptedException ex) {
// (Re-)Cancel if current thread also interrupted
es.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
}

Why java thread behave so differently if they shouldnt in this scenario?

I have a thread sleep problem. Inside the thread run method i have a synchronized block, and a sleep time.
Each thread increments or decrements the shared class "value" in 5 units, and then sleeps.
public class borr {
public static void main(String[] args) {
int times=5;
int sleeptime=1000;
int initial=50;
Shared shared = new Shared(initial);
ThreadClass tIncrement = new ThreadClass(shared,times,sleeptime,true);
ThreadClass tDecrement = new ThreadClass(shared,times,sleeptime,false);
tIncrement.start();
tDecrement.start();
}
}
class Shared{
int value=0;
public Shared(int value) {
super();
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
class ThreadClass extends Thread{
Shared shared;
int times=0;
int sleeptime=0;
boolean inc;
public ThreadClass(Shared shared, int times, int sleeptime, boolean inc) {
super();
this.shared = shared;
this.times = times;
this.sleeptime = sleeptime;
this.inc = inc;
}
public void run() {
int aux;
if(inc) {
for(int i=0;i<times;i++) {
synchronized(shared) {
aux=shared.getValue()+1;
shared.setValue(aux);
System.out.println("Increment, new value"+shared.getValue());
try {
Thread.sleep(sleeptime);
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
else {
for(int i=0;i<times;i++) {
synchronized(shared) {
aux=shared.getValue()-1;
shared.setValue(aux);
System.out.println("Decrement, new value"+shared.getValue());
try {
Thread.sleep(sleeptime);
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
}
}
But if I move the Thread.sleep out of the synchronized block, like this, the output is increment, decrement, increment, decrement. When it stops sleeping and starts a new iteration of the loop, shouldn't the other thread try to enter? instead, it continues looping until that thread is finished:
for(int i=0;i<times;i++) {
synchronized(shared) {
aux=shared.getValue()-1;
shared.setValue(aux);
System.out.println("Decrement, new value"+shared.getValue());
}
try {
Thread.sleep(sleeptime);
}catch(Exception e) {
e.printStackTrace();
}
}
This is bad:
for(...) {
synchronized(some_lock_object) {
...
}
}
The reason it's bad is, Once some thread, A, gets into that loop, then every time it unlocks the lock, The very next thing it does is to lock the lock again.
If the loop body takes any significant amount of time to execute, then any other thread, B, that's waiting for the lock will be put into a wait state by the operating system. Each time thread A releases the lock, thread B will start to wake up, but thread A will be able to re-acquire it before thread B gets a chance.
This is a classic example of starvation.
One way around the problem would be to use a ReentrantLock with a fair ordering policy instead of using a synchronized block. When threads compete for a fair lock, the winner always is the one that's been waiting the longest.
But, fair locks are expensive to implement. A far better solution is to always keep the body of any synchronized block as short and as sweet as possible. Usually, a thread should keep a lock locked for no longer than it takes to assign a small number of fields in some object.
In variant A you use two threads that ...
repeat 5 times
enter a sync block
increment
wait 1 second
repeat 5 times
enter a sync block
decrement
wait 1 second
In variant B you use two threads that ...
repeat 5 times
enter a sync block
increment
wait 1 second
repeat 5 times
enter a sync block
decrement
wait 1 second
In variant A both threads are active (= stay in a sync block) all the time.
In variant B both threads are sleeping most of the time.
As there is absolutely no guarantee which threads are executed next, it is not surprising that variant A and B behave so differently. While in A both threads could - in theory - be active in parallel, the second thread has not much chance to be active as not being in a synchronization context does not guarantee that a context switch is performed at that moment (and another thread is run). In variant B that is completely different: As both threads sleep most of the time, the runtime environment has no other chance as running another thread while one is sleeping. A sleep will trigger switching to another thread as the VM tries to make the best of existing CPU resources.
Nevertheless: The result AFTER both threads have been run will be exactly the same. This is the only determinism you can rely on. Everything else depends on specific implementation details how the VM will handle threads and synchronizations blocks and can even vary from OS to OS or one implementation of a VM to another.
But if i move the Thread.sleep out of the synchronized block, like this, the output is increment, decrement, increment, decrement. The sleep is still inside each iteration of the loop so, shouldnt the result be the same in both cases?:
when it stops sleeping and starts a new iteration of the loop, shouldn't the other thread try to enter.
They both try to enter.
And the other one is already in a wait status (i.e. not actively running) because it tried to enter before. Whereas the thread that has just released the lock can run on and get the now uncontested lock right back.
This is a race condition. When both threads want the lock at the same time, the system is free to choose one. It seems it picks the one that a few instructions ago just released it. Maybe you can change this by yield()ing. Maybe not. But either way, it is not specified/deterministic/fair. If you care about execution order, you need to explicitly schedule things yourself.

Java synchronization and data consistency

Consider the following simple example:
public class Example extends Thread {
private int internalNum;
public void getNum() {
if (internalNum > 1)
System.out.println(internalNum);
else
System.out.println(1000);
}
public synchronized modifyNum() {
internalNum += 1;
}
public void run() {
// Some code
}
}
Let's say code execution is split in two threads. Hypothetically, following sequence of events occurs:
First thread accesses the getNum method and caches the internalNum which is 0 at the moment.
At the very same time second thread accesses modifyNum method acquiring the lock, changes the internalNum to 1 and exits releasing the lock.
Now, first thread continues it execution and prints the internalNum.
The question is what will get printed on the console?
My guess is that this hypothetical example will result in 1000 being printed on the console because read and write flushes are only forced on a particular thread when entering or leaving the synchronized block. Therefore, first thread will happily use it's cached value, not knowing it was changed.
I am aware that making internalNum volatile would solve the possible issue, however I am only wondering weather it is really necessary.
Let's say code execution is split in two threads.
It doesn't exit. However a ressource (method, fields) may be accessed in concurrent way by two threads.
I think you mix things. Your class extends Thread but your question is about accessing to a resource of a same instance by concurrent threads.
Here is the code adapted to your question.
A shared resource between threads :
public class SharedResource{
private int internalNum;
public void getNum() {
if (internalNum > 1)
System.out.println(internalNum);
else
System.out.println(1000);
}
public synchronized modifyNum() {
internalNum += 1;
}
public void run() {
// Some code
}
}
Threads and running code :
public class ThreadForExample extends Thread {
private SharedResource resource;
public ThreadForExample(SharedResource resource){
this.resource=resource;
}
public static void main(String[] args){
SharedResource resource = new SharedResource();
ThreadForExample t1 = new ThreadForExample(resource);
ThreadForExample t2 = new ThreadForExample(resource);
t1.start();
t2.start();
}
}
Your question :
Hypothetically, following sequence of events occurs:
First thread accesses the getNum method and caches the internalNum
which is 0 at the moment. At the very same time second thread accesses
modifyNum method acquiring the lock, changes the internalNum to 1 and
exits releasing the lock. Now, first thread continues it execution and
prints the internalNum
In your scenario you give the impression that the modifyNum() method execution blocks the other threads to access to non synchronized methods but it is not the case.
getNum() is not synchronized. So, threads don't need to acquire the lock on the object to execute it. In this case, the output depends simply of which one thread has executed the instruction the first :
internalNum += 1;
or
System.out.println(internalNum);

Making Java Volatile to work

I done example program to understand how volatile work. In the below example Even without volatile the program work fine. Could some one help me to understand how the program works fine without volatile?
public class VolatileExp {
private /*volatile*/ boolean statusFlag=false;
private void changeState() {
try {
int counter=0;
while (!statusFlag) {
System.err.println("counter: "+counter++);
//Thread.sleep(100);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
final VolatileExp hello = new VolatileExp();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
hello.changeState();
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2000);
hello.statusFlag=true;
System.err.println("setting the status flag ");
} catch (Exception e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
There are several reasons why you can’t observe missing updates for your non-volatile variable.
As pointed out by others in the comments, you can’t rely on failures to happen. In this very example, your program runs too short, so the optimizer won’t make any effort here. Running your program with the       -server option will change that.
Further, you are executing a System.err.println(…); statement within the loop which is internally synchronized. Hence, the heap variables will be re-read in every iteration unless the optimizer decides to enlarge the synchronized code block to cover the entire loop (which is rather unlikely as this would imply holding a lock forever). So after the heap value changed, sooner or later, the first thread will eventually read the changed flag.
Since the second thread also invokes System.err.println(…); after changing the flag it will be forced to actually write the updated values to the heap so both threads are implicitly synchronized on System.err. But even without doing the printout the second thread will eventually write the value to the heap as the thread ends afterwards.
So you have a program that works on most systems due to side-effects but is still broken. Note that in theory the first thread running in a loop consuming 100% CPU time could force the second thread to never run and thus never set the termination flag. However, most today’s systems will preemptively switch between threads.
Even if it worked every time, relying on it was very dangerous as it is not easy to see the side-effects on which it relies which means, simple changes like removing the print statement in the first thread and running with the -server option (or on any other JVM performing similar optimizations) would turn the program from accidentally running into likely breaking.

Java thread join 3

The program creates thread t0 which spawns thread t1 and subsequently threads t2 and t3 are created.After the execution of thread t3and the application never returns to the other threads spawned earlier(t0,t1,t2) and they are left stuck.
Why are the threads t0, t1, and t2 suspended?
public class Cult extends Thread
{
private String[] names = {"t1", "t2", "t3"};
static int count = 0;
public void run()
{
for(int i = 0; i < 100; i++)
{
if(i == 5 && count < 3)
{
Thread t = new Cult(names[count++]);
t.start();
try{
Thread.currentThread().join();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
System.out.print(Thread.currentThread().getName() + " ");
}
}
public static void main(String[] a`)
{
new Cult("t0").start();
}
}
The most important point you missed:
Thread.currentThread().join();
Method join in source code uses isAlive method.
public final synchronized void join(long millis)
...
if (millis == 0) {
while (isAlive()) {
wait(0);
}
...
}
It means that Thread.currentThread().join() will return only when Thread.currentThread() is dead.
But in your case it's impossible because of your running code in Thread.currentThread() has itself
this peace of code Thread.currentThread().join(). That's why after Thread 3 completion your program should hang and nothing happens thereafter.
Why are the threads t0, t1, and t2 suspended? The execution of thread t3 completes.
t3 completes because it is not trying to fork a 4th thread and therefore is not trying to join() with it's own thread. The following line will never return so t0, t1, and t2 all stop there and wait forever:
Thread.currentThread().join();
This is asking the current thread to wait for itself to finish which doesn't work. I suspect that you meant to say t.join(); which is waiting for the thread that was just forked to finish.
Here are some other thoughts about your code in no apparent order:
You should consider implements Runnable instead of extends Thread. See here: "implements Runnable" vs. "extends Thread"
You are using the shared static variable count in multiple threads without any protection of locking. The best solution is to use an AtomicInteger instead of a int. You probably don't have a problem here because each thread is modifying count and then forking another thread but if you tried to fork 2 threads, this would be a real problem because of data race conditions.
I'm not sure why you are only spawning another thread if(i == 5 && count < 3). i is only going to be 5 once in that loop. Is that really what you intended?
String[] names = {"t1", "t2", "t3"}; fields are recommended to be declared at the top of classes. Otherwise they get buried in the code and get lost.
In main you start a Cult thread and then the main thread finishes. This is unnecessary and you can just call cult.run(); in main instead and use the main thread.
Cult(String s) { super(s); } there is no point in having a constructor that calls the super constructor with the same arguments. This can be removed.
This is debatable but I tend to put main method at the top of the class and not bury it since it is the "entrance" method. Same thing with constructors. Those should be above the run() method.
catch(Exception e) {} is a really bad pattern. At the very least you should do a e.printStackTrace(); or log it somehow. Catching and just dropping exceptions hides a lot of problems. Also, catching Exception should be changed to catch(InterruptedException e). You want to restrict your catch blocks just the exceptions thrown by the block otherwise this may again hide problems in the future if you copy and paste that block somewhere.
More a good practice but never use constants like 3 that have to match another data item. In this case it would be better to use names.length which is 3. THis means that you don't need to change 2 places in the code if you want to increase the number of threads. You could also have the name be "t" + count and get rid of the names array altogether.

Categories

Resources