7

After surfing the web, I am still confused about the following thread behavior. I am aware that static variables are shared within the same classloader, however there's sth definitely missing in this extract:

public class parallelCounter { public static final int N = 100000000; public static int j = 0; public static void inc() { for (int i = 0; i < N; i++) { j++; } System.out.println(j); // 10000000 } } class parallelCounterDemo { public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { parallelCounter.inc(); } }); t1.start(); System.out.println(parallelCounter.j); // 0 Why? } } 
3
  • 1
    As alluded to below; 't1' hasn't started (or at least, finished) by the time you print the value. Try 't1.join()' after starting it. This will wait for it to finish before continuing. Commented Jul 17, 2017 at 12:50
  • ..yes, you have to t1.join() (or wait) to expect any values calculated by inc() Commented Jul 17, 2017 at 12:53
  • Thanks much, community Commented Jul 17, 2017 at 13:22

5 Answers 5

1

There are two things to note here:

  1. Your code has a race-condition in that the state when printing depends on the execution speed of the two independent threads. Most times t1 will not even have started executing inc when your println executes. You might try adding a sleep(100) or something after t1.start.

  2. You have to take care that not all changes to variables made by one thread will be instantly visible to other threads - this is a pretty complex topic where you have to check which constucts will result in data-synchronization between threads. For you example the easiest way could be to declare j as public static volatile int.

Sign up to request clarification or add additional context in comments.

Comments

1

Your code, in the current state, has a concurrency issue as two Threads try to access the static int variable at the same time (without synchronization):

  • Main Thread tries to read the value of the variable
  • t1 Thread tries to write the value of the variable

The Syso outputs 0, because the run method of the t1 thread hasn't started yet (no increments were done). But this is not 100% guaranteed to happen all the time.

If you want to be sure that the t1 thread finishes its execution before doing the Syso in main, you should use the join method:

public class parallelCounter { public static final int N = 100000000; public static int j = 0; public static void inc() { for (int i = 0; i < N; i++) { j++; } System.out.println(j); // 10000000 } } class parallelCounterDemo { public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { parallelCounter.inc(); } }); t1.start(); try { t1.join(); // Wait for thread to finish } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(parallelCounter.j); } } 

Comments

0

t1 is a new Thread which start asynchronous and your code continue without calling inc() function so j number is still 0

Comments

0

When you call System.out.println(parallelCounter.j);, your parallelCounter.inc(); function in your thread still hasn't ended. So j's value is still unincremented, at 0. Replace your for loop by a simple assignment, and add a Thread.sleep(1000); after starting your Thread t1, and you'll get the desired behaviour.

Comments

0

I did not run your code, but I assume that the method call System.out.println(parallelCounter.j); occured to soon within the program's execution flow.

You started the thread and then your code prints the value of j immediately. I think that the thread did not have enough time to start the run() method.

I suggest that you insert some waiting period before you print j, e.g.

Thread.currentThread().sleep(3000); // 3 seconds wait

2 Comments

Be careful with this duration: he has to iterate a million time, so if the code doesn't get optimized by the compiler, 3 seconds will probably be too short.
You are absolutely right @Nathan ... I suggested the 3 second wait just to see how the value changed properly. For outputing the correct and final value a join would be the best solution, e.g. t1.join() to wait until the thread has finished.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.