Why can yielding a thread solve the thread visibility problem in Java - java

Consider the following code:
public class Test {
static boolean moreLoop = true;
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(() -> {
while (moreLoop) {
// more loop
}
System.out.println("loop exited");
});
Thread t2 = new Thread(() -> {
moreLoop = false;
});
t1.start();
Thread.sleep(1000); // so we have more confidence t1 runs first
t2.start();
}
}
After running the code, the "loop exited" statement never gets printed. I understand this is because thread 2 puts the updated boolean in the cache of the CPU in which it's running, so thread 1 can not see the change if it's running in a different CPU. If we make the moreLoop variable volatile then "loop exited" will soon be printed.
Here's the thing. If we leave moreLoop non-volatile and write Thread.currentThread().yield(); on the line after // more loop inside the while loop, we will see "loop exited" printed. Using Thread.sleep will achieve the same effect. Why is that? Does thread 1 sync with thread 2 when it is restored?
I ask this question because my company has a WebApp written in Java that never uses volatile on the shared hash maps and the code has been working for years. My guess is that because the HTTP threads are managed by tomcat, they might get scheduled out after finishing one HTTP request and before serving the next one, just like what I described in the above paragraph. Is this possibly the reason why the code works?
Edit: If we don't use either volatile or yiled/sleep, it seems thread 1 can still see the change made by thread 2 as long as the change by thread 2 is made before the while loop starts. For example, after running the following code
public class Test {
static boolean moreLoop = true;
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(() -> {
System.out.println("thread 1 started");
for (long i = 0; i < 10_000_000_000L; ++i); // takes around 3 seconds on my machine
System.out.println("thread 1 warmup finished");
while (moreLoop) {
// more loop
}
System.out.println("loop exited");
});
Thread t2 = new Thread(() -> {
System.out.println("thread 2 started");
moreLoop = false;
System.out.println("thread 2 finished");
});
t1.start();
Thread.sleep(1000); // so we have more confidence t1 runs first
t2.start();
}
}
it prints the following on my machine
thread 1 started
thread 2 started
thread 2 finished
thread 1 warmup finished
loop exited
We don't have any synchronization. Well, you may argue System.out.println does the synchronization. But after I removed all println statements except "loop exited", the code could still print "loop exited". How come thread 1 could see the change made by thread 2?

Related

java when I invoked Thread.sleep(), the data's visibility

Look at this code:
public class VolatileTest {
private static boolean ready = false;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(){
#Override
public void run() {
ready = true;
System.out.println("t2 thread should stop!");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread(){
#Override
public void run() {
while(!ready){
System.out.println("invoking..");
}
System.out.println("I was finished");
}
};
t1.start();
t2.start();
}
}
I think the result of this code maybe:
t2 thread should stop!
invoking..
I was finished
because of in the multithreading, when the t1 modify 'ready' variable to true,then I made t1 sleep. At the moment, I think, to t2 the 'ready' variable is false!!! because t1 thread is not stop, the variable in t1 is invisible in t2.
But in fact.. I test many times. the result is always this:
Am my idea is wrong?
First of all, despite calling your class VolatileTest, you are not actually using volatile anywhere in your code.
Since the ready variable is not declared as volatile AND you are accessing it without any explicit synchronization, the behavior is not specified. Specifically, the JLS does not say whether the assignment made in thread 1 to the ready variable will be visible within thread 2.
Indeed, there is not even guaranteed that the run() method for thread 1 will be called before the run() method for thread 2.
Now it seems that your code (as written!) is behaving in a way that is consistent with the write of true always being visible immediately. However, there is no guarantee that that "always" is actually always, or that this will be the case on every Java platform.
I would not be surprised if the syscall associated with sleep is triggering memory cache flushing before the second thread is scheduled. That would be sufficient to cause consistent behavior. Moreover, there is likely to be serendipitous synchronization1 due to the println calls. However, these are not effects you should ever rely on.
1 - Somewhere in the output stream stack for System.out, the println call is likely to synchronize on the stream's shared data structures. Depending on the ordering of the events, this can have the effect of inserting a happens before relationship between the write and read events.
As I mentioned in my comment, there are no guarantees. ("There is no guarantee what value thread t2 will see for ready, because of improper synchronization in your code. It could be true, it could be false. In your case, t2 saw true. That is consistent with "there is no guarantee what value t2 will see")
You can easily get your test to fail by running it multiple times.
When I run below code that does your test 100 times, I always get 14-22 "notReadies", so 14-22% of the cases you will not see the change to ready in Thread t2.
public class NonVolatileTest {
private static boolean ready = false;
private static volatile int notReadies = 0;
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 100; i++) {
ready = false;
// Copy original Thread 1 code from the OP here
Thread t2 = new Thread() {
#Override
public void run() {
if (!ready) {
notReadies++;
}
while (!ready) {
System.out.println("invoking..");
}
System.out.println("I was finished");
}
};
t1.start();
t2.start();
// To reduce total test run time, reduce the sleep in t1 to a
// more suitable value like "100" instead of "5000".
t1.join();
t2.join();
}
System.out.println("Notreadies: " + notReadies);
}
}

Java Thread join() behavior

public class RunTest {
public static int counter = 0;
static class RunnerDec implements Runnable{
public void run(){
for(int i=0;i<5000; i++){
counter--;
}
}
}
static class RunnerInc implements Runnable{
public void run(){
for(int i=0;i<5000; i++){
counter++;
}
}
}
public static void main(String[] args) {
RunnerDec rd = new RunnerDec();
RunnerInc ri = new RunnerInc();
Thread t1 = new Thread(rd);
Thread t2 = new Thread(ri);
t1.start();
t2.start();
try{
t1.join(); // this will stop the main thread until t1 is done incrementing 5000 times
t2.join(); // this will stop the main thread until t2 is done incrementing 5000 times
}catch(Exception e){
e.printStackTrace();
}
System.out.println(counter);
}
}
I expect the result to be 0 every time alas this is not the case. The java doc says join() "waits for this thread to die". I feel like the main thread should wait for t1 to finish then wait for t2 to finish. That's not what is happening. Thanks for the clarity!!
It does wait for the threads to die. But your two threads concurrently update a shared variable without any synchronization, so you're seeing race conditions and visibility issues.
For example:
counter = 1000
thread 1 reads counter : 1000
thread 2 reads counter : 1000
thread 1 increments and writes counter: 1001
thread 2 decrements and writes counter: 999
Since ++ and -- are not atomic operations, the above thread interlacing example loses an increment.
The easiest way to fix them is to use an AtomicInteger rather than an int. To understand the crux of the problem, you'd better read Java Concurrency in Practice, or at the very least the Java concurrency tutorial.

How can a loop be completed by two thread? say loop from count=1 to count=4 by ist thread and count =5 to 8 by 2nd thread?

Description of how i want the output :
I want two threads Gaurav and john to complete a while loop(from 1 to 8), such that whichever thread starts ist, runs for 5 iterations(i.e. till count=5) , then go to sleep and then next thread completes the loop (run for count=6 to count=8). Program should end then.
For this scenario , i created a instance variable count and incrementing its value in counter method
Problem is : i am getting a weird output (output attached at the end ) even after synchronizing the counter method (counter method increments count variable)
public class ThreadCounter implements Runnable {
private int count;
#Override
public void run(){
try {
counter(); // call synchronized counter function
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//end of run()
public synchronized void counter() throws InterruptedException{
while(true){
// i want the loop to increment count from 1 to 4 by ist thread(whichever thread runs ist) and then 5 to 8 by next thread
System.out.println("Which thread running ? " +Thread.currentThread().getName());
count++;
System.out.println("count is"+count);
if (count==5){
System.out.println("count is"+count +" and Thread is " +Thread.currentThread().getName());
// when count is 5 make the current thread should go to sleep
Thread.currentThread().sleep(7000);
}// if count==5 ends here
//whichever thread starts now , should start the counter from count=5
if (count==8){
break;
// when count is 5 make the current thread go to sleep
}
}// while loop ends here
}// end of counter()
}// end of class ThreadingIst
public class ThreadTest {
public static void main(String [] args){
Thread t1= new Thread(new ThreadingIst());
Thread t2= new Thread(new ThreadingIst());
t1.setName("John");
t2.setName("Gaurav");
t1.start();
t2.start();
}// main ends here
}
Output is :
Which thread running ? John
count is1
Which thread running ? John
count is2
Which thread running ? John
count is3
Which thread running ? John
count is4
Which thread running ? John
count is5
count is5 and Thread Johnis going to sleep
Which thread running ? Gaurav
count is1
Which thread running ? Gaurav
count is2
Which thread running ? Gaurav
count is3
Which thread running ? Gaurav
count is4
Which thread running ? Gaurav
count is5
count is5 and Thread Gauravis going to sleep
Which thread running ? Gaurav
count is6
Which thread running ? Gaurav
count is7
Which thread running ? Gaurav
count is8
count is8 and Thread Gauravis coming out of loop
Which thread running ? John
count is6
Which thread running ? John
count is7
Which thread running ? John
count is8
count is8 and Thread Johnis coming out of loop
I have gone through an answer - "implements Runnable" vs. "extends Thread" , in which one of the comment is However, one significant difference between implementing Runnable and extending Thread is that
by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.
so , if threads can share the same object , then the instance value like count should be shared by both. Why is my output like this then.
To achieve that you can create two threads, and make one waiting for the other, you can read about joining a thread here:
http://docs.oracle.com/javase/tutorial/essential/concurrency/join.html
I was thinking in something like:
public class Counter extends Thread {
private final int countFrom;
private final int countTo;
private final Counter counterToWaitFor;
public Counter(final int countFrom, final int countTo, final Counter counterToWaitFor) {
super();
this.countFrom = countFrom;
this.countTo = countTo;
this.counterToWaitFor = counterToWaitFor;
}
#Override
public void run() {
if (this.counterToWaitFor != null) {
try {
this.counterToWaitFor.join();
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
for (int i = this.countFrom; i <= this.countTo; i++) {
System.out.println("i= " + i);
}
}
}
and in the main:
public static void main(final String[] args) throws IOException, InterruptedException {
final Counter t1 = new Counter(1, 5, null);
final Counter t2 = new Counter(6, 8, t1);
t1.start();
t2.start();
}
A simple solution is to use the Java 8 Streams API
IntStream.rangeClosed(1, 8).parallel()
.forEach(System.out::println);
This can use all the CPUs in your machine with a lot less code.
by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.
Actually it makes no difference in this regard, you can do either in both cases.
The reason to avoid sub-classing Thread is to avoid confusion when calling overridden methods.
Why is my output like this then.
You are sharing an object without thread safety.

Java: Thread doesn't work

I'm trying to start a thread in a for-loop. This task should only wait for a second (Thread.sleep()), so every time the loop starts over again, a new thread is started and it should cause the code after the thread to wait until it is executed.
public void count()
{
for(int i = 29; i>=0; i--)
{
Thread t1;
t1 = new Thread(new TimerClass());
t1.start();
String s = String.valueOf(i);
jLabel6.setText(s);
System.out.println(s);
}
}
public class TimerClass implements Runnable{
#Override
public void run()
{
try{
Thread.sleep(1000);
System.out.println("Timer");
} catch(InterruptedException e)
{
}
}
}
As you can see, I implemented in both methods System.out.println() to check if they are actually executed. I get this:
29
28
27
26
...//25 - 3
2
1
0
Timer
Timer
Timer
//in all 29 times Timer
So it should be 29, Timer, 28, Timer and so on, but it isn't.
Does anyone know what's wrong with the code?
Thanks a lot.
Your main loop that is starting the thread is likely dominating the CPU, so it finishes doing its entire loop and only then do the threads get a chance to go.
In fact, given that all of your threads sleep for an entire second and you're only looping 29 times, you're guaranteed that your loop will finish (and print all of the numbers) before your threads do. Add a sleep to your main loop if you want the threads to print - remember, the main loop doesn't stop when you start a thread.
You can join a thread to the main thread so first your thread will finished then main thread
public void count()
{
for(int i = 29; i>=0; i--)
{
Thread t1;
t1 = new Thread(new TimerClass());
t1.start();
t1.join();
String s = String.valueOf(i);
jLabel6.setText(s);
System.out.println(s);
}
}
Here is my code for spawning 2 threads or one thread depends on arrayList size but in my case this threads are doing much more complex tasks then just waiting 1 sec
for (int i = 0; i < array.size(); i += 2) {
Thread t1 = null;
Thread t2 = null;
if (i < array.size() - 1 && array.size() > 1) {
t1 = new Thread(array.get(i));
t2 = new Thread(array.get(i + 1));
t1.start();
t2.start();
}
else {
t2 = new Thread(array.get(i));
t2.start();
}
if (t1 != null)
t1.join();
if (t2 != null)
t2.join();
}
In my code I populate arrayList with Objects that Implements Runnable interface.
Even if you sleep the thread for 1ms, your results would be the same. If you can manage the thread to sleep for the time less than it takes to print the results, your result could be as expected. Here is my code where I have put the time of 1 ms but yet the results are the same.
public class MultiThreading implements Runnable
{
public void run()
{
try
{
Thread.sleep(1);
System.out.println("Timer");
}
catch(Exception e)
{
}
}
public static void main(String [] args)
{
for(int i = 29; i>=0; i--)
{
Thread t1;
t1 = new Thread(new MultiThreading());
t1.start();
String s = String.valueOf(i);
System.out.println(s);
}
}
}
If you comment out the Thread.sleep(1) method, then your results are as you expected.
Delay is much enough to let the for loop in count() to finish before is can print 'timer' from thread.
What is happening is that the thread you started starts executing and immediately goes to sleep. In the meantime, your loop just keeps running. As the whole point of threads is that they run asynchronously, I don't really understand why you think your main loop should be waiting for it to finish sleeping. The thread has started running and is now running independently of the main loop.
If you want to wait for the thread you just started to finish (in which case, you might as well use a method), then use one of the synchronisation primitives, i.e. Thread.wait().
What you actually want to do is block your main thread while another thread is running. Please don't use Thread#sleep statements, as these are unreliable in order to "make your application work". What you want to use instead is Thread#join. See dharr his code for an example.
Also, it's better to use Executors and ExecutorServices when creating threads or running async tasks.
Threads are interesting. Think of a virtual thread as a physical thread. There are many threads on the clothes you're wearing, all working at the same time to hold your shirt together. In virtual terms what Thread.start() does is start a thread on a different strand WHILE the following code continues to execute, (i.e. Two Threads work simultaneously like 2 runners run next to each other). Consider putting a break point right after Thread.start(). You'll understand.
For your desired effect, just put a Thread.sleep() in the main loop. This will cause an output of
29
Timer
28
Timer
// etc.
Hope this helped.
Jarod.
Another analogy to the threads in a shirt:
Think of threads as coworkers to your main programm (which is a thread itself). If you start a thread, you hand some work to this coworker. This coworker goes back to his office to work on this task. You also continue to do your task.
This is why the numbers will appear before the first thread/coworker will output anythig. You finished your task (handing out work to other coworkers) before he finished his.
If you want to give out some work and then wait for it to be finished, use t1.join() as suggested by others. But if you do this, it is senseless to create new Threads, because you don't (seem) to want to process something in parallel (with many coworkers) but in a specific order - you can just du it yourself.

How to slow a thread down in JAVA

I have this class in which I run a for loop 10 times. This class implements Runnable interface. Now in main() I create 2 threads. Now both will run loop till 10. But I want to check loop count for each thread. If t1 is past 7 then make it sleep 1 second so as to let t2 complete. But how to achieve this? Please see the code. I attempted but looks totally foolish. Just how to check the data of a thread ???
class SimpleJob implements Runnable {
int i;
public void run(){
for(i=0; i<10; i++){
System.out.println(Thread.currentThread().getName()+" Running ");
}
}
public int getCount(){
return i;
}
}
public class Threadings {
public static void main(String [] args){
SimpleJob sj = new SimpleJob();
Thread t1 = new Thread(sj);
Thread t2 = new Thread(sj);
t1.setName("T1");
t2.setName("T2");
t1.start();
try{
if(sj.getCount() > 8){ // I know this looks totally ridiculous, but then how to check variable i being incremented by each thread??
System.out.println("Here");
Thread.sleep(2000);
}
}catch(Exception e){
System.out.println(e);
}
t2.start();
}
}
Please help
You should use some synchronization object, and not rely on slowing down of threads. I strongly suggest you take a look at one of the classes at java.util.concurrent package. You can use for this CountdownLatch - thread 1 will await on it, and thread 2 will perform the countdown and release the lock, and let thread 1 continue (the release should be done at the end of thread 2 code).
I added a synchronized Block, which can be entered by one thread at a time. Both threads call and enter the method parallel. One thread will win the race and take the lock. After the first thread leaves the block it waits 2 seconds. In this time the second thread can iterate over the loop. I think this behaviour is wanted. If the second thread must not wait 2 seconds, too, you can set some boolean flag, that the first thread finished the block and use this flag in an if statement, which prevents the wait time of the second thread.
class SimpleJob implements Runnable {
int i;
public void run(){
synchronized (this) {
for(i=0; i<8; i++){
System.out.println(Thread.currentThread().getName()+" Running ");
}
}
try {
System.out.println("Here");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(i=0; i<2; i++){
System.out.println(Thread.currentThread().getName()+" Running ");
}
}
public int getCount(){
return i;
}
}
public class Threadings {
public static void main(String [] args){
SimpleJob sj = new SimpleJob();
Thread t1 = new Thread(sj);
Thread t2 = new Thread(sj);
t1.setName("T1");
t2.setName("T2");
t1.start();
t2.start();
}
}
If the goal is to run 2 Runnables in parallel (as Threads) and wait for them both to finish, you can, in increasing order of complexity/power:
Use Thread.join (as suggested by #Suraj Chandran but his reply seems to have been deleted)
Use a CountDownLatch (as also suggested by #zaske)
Use ExecutorService.invokeAll()
EDIT ADDED
First, I don't understand what the magic "if you are at 7 then wait for the other" logic is all about. But, to use Thread.join() from your main code, the code would look like
t1.start(); // Thread 1 starts running...
t2.start(); // Thread 2 starts running...
t1.join(); // wait for Thread 1 to finish
t2.join(); // wait for Thread 2 to finish
// from this point on Thread 1 and Thread 2 are completed...

Categories