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.
Related
package org.multithreading.basics;
public class ThreadJoin {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(counter);
Thread t2 = new Thread(counter);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Numbers counted =" + counter.getCount());
}
}
class Counter implements Runnable {
private int count;
#Override
public void run() {
for (int i = 0; i < 20000; i++) {
count++;
}
}
public int getCount() {
return count;
}
}
Here the output is always >20000 and <40000 and always random value. So in the above code, main tread is waiting for t1 to complete but why not for t2, though the join is there on t1 as well as t2.
The code waits for both threads to finish, 4000 ++ statements will have been executed!
BUT you need to understand how threads work, how their variable access works, what volatile and non-volatile variables are, how synchronisation works, why they differ and why the results you see are perfectly reasonable and 100% expected.
x++ is basically x = x + 1 (this is not a precise explanation but the general thing that is happening here) => if both threads run that statement at the same time you will lose one increment since both read x = 123, both call 123 + 1 => 124 and then both assign 124 to x => two increments called but the value is only increased by one.
As per above code, we have called t1.start() and t2.start() at same time so, both the thread will starting executing task defined inside run method but in next line we have call t1.join therefore main thread will wait for completion of t1 method but still t2 thread is executing in parallel (both threads are reading same count value and update it at same time hence it actually increased once instead of two times) once we called t2.join() then main thread will wait for completion of t2 thread hence we can see output in range of >20000 and <40000
in case you want to fix this data inconsistency issue modify your code as below
#Override
public void run() {
synchronized(this) {
for (int i = 0; i < 20000; i++) {
count++;
}
}
}
Counter counter = new Counter();
Here counter is the common object passed as a reference to both the threads.
for (int i = 0; i < 20000; i++) {
count++;
}
The count variable is incremented by both threads working together.
So, It is illusioned that the main thread waits for t1 to count just above 20000 and terminates without waiting for t2 to complete.
In fact, the main thread waits until both thread increment count just above 20000.
The above explanation is for main thread not waiting for t2.
The count is accessed in an unsynchronized way.
The expression count++ equivalent to count = count+1
Two operations assignment and addition are done in parallel. So, value incremented by t1 may be overwritten by t2. this value will not be in sequence and not constant during execution. So, Every time value of count will vary.
This question already has answers here:
synchronized block for an Integer object
(3 answers)
Closed 5 years ago.
Why doesn't variable named 'count' finally equal to 20000?
public class Main {
private Integer count = 0;
public void increment() {
synchronized (count) {
count++;
}
}
public static void main(String[] args) {
Main app = new Main();
app.doWork();
}
public void doWork() {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i=0; i<10000; i++) {
increment();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i=0; i<10000; i++) {
increment();
}
}
});
t1.start();
t2.start();
System.out.println(count);
}
It seems that thread loses the variable but when does it happen? The same happens in a case of using AtomicInteger too.
P.S. could you please recommend a good course with exercises for learning multithreading in Java?)
Because start creates a new thread, and when you print the count you aren't sure the thread execution is finished.
t1.start();
t2.start();
System.out.println(count); // Here you don't know if t1 and t2 ended their execution
Join threads to wait for them to complete the task:
t1.start();
t2.start();
t1.join(); // wait for t1 to finish
t2.join(); // wait for t2 to finish
System.out.println(count); // 20000
Note: You'll have to handle InterruptedException on join calls.
You synchronize on count. But your code changes count. Different threads synchronizing on different objects don't guarantee atomicity.
Use a separate final monitor object to synchronize on.
See also #BackSlash 's answer for making sure you print the correct end result.
Edit
His answer comes down to : if you print the result without waiting for the threads to finish on your main thread you'll see some intermediate result, or possibly even 0.
So you need to call join(), which blocks until the thread finishes, on both threads before printing the end result.
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.
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...
I'm learning how to work with threads in Java and I need some advice..
I want to print on the standard output numbers from 0..50 with the name of the thread that has done it using three threads.
I have two classes - class Counter that implements Runnable and class Main that creates and runs the threads. Counter has the variable c which is shared among the threads.
My idea was, that I increment c by 1 and then call yield() on the current thread so as the other threads would do the same. Repeat this until c reaches 50.
But it doesen't work, the numbers are printed out in wrong order. How do I fix this?
public class Counter implements Runnable {
Thread t1;
private int c = -1;
public Counter() {
}
public Counter(String name) {
t1 = new Thread(this, name);
t1.start();
}
#Override
public void run() {
while (c < 50) {
increment();
Thread.yield();
}
}
public void increment() {
if (c < 50) {
c++;
System.out.println(Thread.currentThread().getName() + ": " + c);
}
}
}
public class Main {
public static void main(String[] args) throws IllegalThreadStateException {
Counter c1 = new Counter();
Thread t1 = new Thread(c1, "Thread 1");
Thread t2 = new Thread(c1, "Thread 2");
Thread t3 = new Thread(c1, "Thread 3");
t1.start();
t2.start();
t3.start();
}
Edit: In the end I solved it this way. Thank you all who helped me with the tough start with multithreading.
import java.util.concurrent.atomic.AtomicInteger;
public class Counter2 implements Runnable {
// you could also use simple int
private AtomicInteger c = new AtomicInteger(-1);
private static final Object syncObject = new Object();
public Counter2() {
}
#Override
public void run() {
while (c.get() < 50) {
synchronized (syncObject) {
if (c.get() < 50) {
System.out.println(Thread.currentThread().getName() + ": " + c.incrementAndGet());
}
}
}
}
}
Use syncrhonized section in method increment with special static object.
private static final Object syncObj = new Object();
public void increment()
{
syncrhonized( syncObj )
{
c++;
System.out.println(c);
}
}
Or make this method synchronized via its declaration.
But it's wrong idea to store your real data in thread objects. Thread should just to manipulate with share objects but not to store them.\
And actually I don't understand why do you start thread in
Quoting from the javadoc Thread.yield(), emphasis by me:
public static void yield()
A hint to the scheduler that the
current thread is willing to yield its
current use of a processor. The
scheduler is free to ignore this
hint.
...
It is rarely appropriate to use
this method.
Make increment() synchronized in order to prevent other threads from entering the method concurrently.
In conjunction with yield() you should be able to get another thread print the next number (not always since the system might resume the thread that called yield again - see Ingo's answer - , but the order should still be the same).
synchronized increment() would mean that any thread that tries to enter that method on the same object would have to wait if another thread would have aquired the lock already by entering the method.
Yes your code won't work. Thread#yield() won't control the thread scheduler in the manner you desire. I"m curious what result you get. You'll probably get repeated numbers and some number that are slightly out of order.
You could use atomic integer which should remove all duplicates. But since the print statement is not atomic. You may still print your results out of order. So you should probably just synchronize the increment method. Also you don't really need yield so dump it.
If the purpose of the problem is to go from thread 1 to thread 2 to thread 3 back to thread 1, etc... Such that the results are
Thread 1:0
Thread 2:1
Thread 3:2
Thread 1:3
Thread 2:4
Thread 3:5
Thread 1:6
Thread 2:7
....
Then you'll need to lock the increment method and use wait and notifyAll. wait will cause other threads to halt processing until the current thread notifies them to start again.