Global Thread Variable in Java

I am trying to understand the thread safety mechanism in java and I need help. I have a class:

public class ThreadSafe { private Executor executor = new ScheduledThreadPoolExecutor(5); private long value = 0; public void method() { synchronized (this) { System.out.println(Thread.currentThread()); this.value++; } } private synchronized long getValue() { return this.value; } public static void main(String... args) { ThreadSafe threadSafe = new ThreadSafe(); for (int i = 0; i < 10; i++) { threadSafe.executor.execute(new MyThread()); } } private static class MyThread extends Thread { private ThreadSafe threadSafe = new ThreadSafe(); private AtomicBoolean shutdownInitialized = new AtomicBoolean(false); @Override public void run() { while (!shutdownInitialized.get()) { threadSafe.method(); System.out.println(threadSafe.getValue()); } } } } 

Here I am trying to make the value stream safe, accessed by only one stream at a time. When I run this program, I see that there is more than one thread in value , even if I wrap it in a synchronized block. Of course, this loop will be infinite, but this is just an example, I will stop this program manually after a few seconds, so I have:

 2470 Thread[pool-1-thread-3,5,main] 2470 Thread[pool-1-thread-5,5,main] 2470 Thread[pool-1-thread-2,5,main] 

Access to various streams and their change value . Can someone explain to me why this is so? And how to make this global variable thread safe?

+7
source share
2 answers

Each thread has its own ThreadSafe , and each ThreadSafe has its own, different value . In addition, synchronized methods are blocked on this , so each ThreadSafe locked on its own - and not one of them is shared between threads. This is called a thread, and it is the easiest way to ensure thread safety. :)

To get the experiment that I think you need, you need to modify MyThread so that its constructor accepts the ThreadSafe argument (instead of creating it). Then, the main method, create one ThreadSafe and pass it to each MyThread at build time.

+10
source

You get the same value every time, because each of your Runnable has its own instance of the ThreadSafe class.

If you want all of them to share the same class, you will need to have only one instance of ThreadSafe and pass it to all your tasks - see below. As already mentioned, AtomicLong is the way to go if you want a thread-safe shared long .

In addition, your MyThread class should not extend Thread . It should instead implements Runnable . Your code works because Thread already implements Runnable . If you executed myThread.interrupt() , this will not actually interrupt the thread, because these are thread pool threads that call your run() method.

The following will work:

 ThreadSafe threadSafe = new ThreadSafe(); for (int i = 0; i < 10; i++) { threadSafe.executor.execute(new MyRunnable(threadSafe)); } ... private static class MyRunnable implements Runnable { private final ThreadSafe threadSafe; public MyRunnable(ThreadSafe threadSafe) { this.threadSafe = threadSafe; } ... 
+4
source

All Articles