Synchronized method not threadsafe - java

Can someone please let me know why is the below code not threadsafe ? The output I get is either 0 or 45 or 90. The shared resource counter has a synchronized method, so I am expecting 90 as the output all the times. Am I missing something here ? Please advise.
Kindly, also let me know how to make this code threadsafe.
class Counter{
long count = 0;
public synchronized void add(long value){
this.count += value;
}
}
class CounterThread extends Thread{
protected Counter counter = null;
public CounterThread(Counter counter){
this.counter = counter;
}
public void run() {
for(int i=0; i<10; i++){
counter.add(i);
}
}
}
public class Example {
public static void main(String[] args){
Counter counter = new Counter();
Thread threadA = new CounterThread(counter);
Thread threadB = new CounterThread(counter);
threadA.start();
threadB.start();
System.out.println(counter.count);
}
}

wait for threads to finish. Add
threadA.join();
threadB.join();
before printing the result.

Essentially you are reading the values before the two threads have completed their execution.
You can use a join to wait for the threads to finish.
Also try using AtomicLong 's addAndGet method instead of the synchronized add method.

You do not wait with the println until the threads have stopped. So you print out the value of the counter while the for-loops are still in process. It does not have to do anything with thread-safety.

Counter access is threadsafe, but System.out.println(counter.count); can happen before other threads do their work.

Your code is thread safe but a better way is get rid of synchronized method and use AtomicLong
And Use getAndAdd(long) method
public final long getAndAdd(long delta)
>Atomically add the given value to current value.

You have 3 threads running there. The one assigned to variable threadA, the one assigned to threadB and the main thread.
The main thread runs as long as the main method runs. The other 2 are started and run concurrently with the main thread. However, the main thread is not blocked waiting for the other 2 to finish, so it prints the result when it gets a chance to execute.

Related

Why do these synchronized methods keep giving me different outputs?

I need this threads that have access to the same data to be execute simultaneously without messing around with each other, so instead using Thread.join() I've been trying with synchronized methods. Problem is that I see no change at all, it keep giving me the same result that I had before using them. I don't even know what exactly I'm doing wrong, synchronized
methods suppose to prevent other synchronized methods to execute until they are done, right? Hope you can give me some clue about what is goin' on.
public class ThreadSync{
public static void main(String[] args) throws InterruptedException {
//if execute properly
//output can't be other than 0
while(true) {
ChangeValue counter = new ChangeValue();
Threads t = new Threads(counter,"up");
Threads t2 = new Threads(counter,"down");
Threads t3 = new Threads(counter,"print");
t.start();
t2.start();
t3.start();
}
}
}
class Threads extends Thread{
Threads(ChangeValue obj, String act){
counter = obj;
action = act;
}
#Override
public void run() {
switch(action) {
case ("up"): counter.up(); break;
case ("down"): counter.down(); break;
case ("print"): counter.print(); break;
}
}
ChangeValue counter;
String action;
}
class ChangeValue{
public synchronized void up() { value++; }
public synchronized void down() { value--; }
public synchronized void print() { System.out.println(value); }
public int value = 0;
}
The synchronization just ensures that the methods are not executed at the same time. However, it does not guarantee any execution order.
You need to ensure that print() is not executed before the other threads have terminated. This could be achieved by joining the threads. To do so, execute
t.join();
t2.join();
either before starting the print thread or before executing its logic.
Note that the synchronization is still sensible because it ensures that the increment and decrement operations are executed atomically. That is, that reading, incrementing, and writing count when executing count++ are executed at once
(see also: Why is i++ not atomic?). Thereby it prevents the following execution sequence:
[Thread "up"]: load count with value 0
[Thread "down"]: load count with value 0
[Thread "up"]: increment count to 1
[Thread "down"]: decrement count to -1
[Thread "up"]: store count with value 1
[Thread "down"]: store count with value -1
(This is a "lost update" in database terms.)
synchronized prevens your thread from accessing the field simultaneously, but of course it provides no guarantee regarding the order in which the threads execute.
For example, if, by pure chance, the "Up" thread executes first, the "Print" thread second and the "Down" thread last, the output will be 1, even though the counter value is 0 after all threads are finished.

Thread execution after .start() method

I am wondering what happens in the following scenario:
Two threads are created:
Thread t1 = new Thread();
Thread t2 = new Thread();
Assume these just print out a string, the threads then call the .start() method:
t1.start();
t2.start():
My question is why do these threads print in a seemingly random order each time? I know threads execute concurrently but would t1 not always finish before t2 due to the sequential execution of the main process?
Calling start() on a Thread doesn't necessarily result in the thread running immediately after. It is possible for other things to happen in between your calling start() and the first line of your thread's run() method actually being run. And even once your run() is actually running, it's also possible that other things happen before, during, or after your run() method finishes.
In your question, you said: "assume these just print out a string" – here's an implementation of run() which does that:
public void run() {
System.out.println("my name is: " + getName());
}
So it's possible that t1 starts to run first, but before it actually calls System.out.println, t2 is allowed to execute and runs to completion, then t1 is resumed.
If this kind of behavior won't work for your use case, you'll need to add some kind of concurrency protection to coordinate how and when your threads run.
UPDATE:
To illustrate the unpredictable sequence of thread execution, run this code a few times and observe the output:
public class Example {
public static void main(String[] args) {
for (int k = 0; k < 10; k++) {
new TestThread(k).start();
}
}
}
class TestThread extends Thread {
private final int k;
TestThread(int k) {
this.k = k;
}
#Override
public void run() {
System.out.print(k + " ");
}
}
Here is the output from one of my local runs:
7 0 1 5 4 6 3 2 8 9
Thread.start() doesn't guarantee execution. It will just make the Thread state runnable and hand over to the Thread Scheduler. It is the Thread Scheduler which decides which thread to run when.
If you need code to execute in a defined order on multiple threads, you need to add synchronization code between those threads.
Otherwise, the system is free to schedule execution in any order it sees fit.

Invoking synchronized getter and setter

I am trying to practice synchronize keyword with methods.
I wrote the following code:
Adder class:
public class Adder implements Runnable{
Counter counter;
Adder(Counter counter){
this.counter = counter;
}
public void run() {
for (int i=0; i<100; i++)
counter.setCount(counter.getCount()+1);
}
}
Counter class:
public class Counter {
private int count = 0;
public synchronized void setCount(int val){
count = val;
}
public synchronized int getCount(){
return count;
}
}
main:
public class main {
public static void main(String[] args) {
Counter counter = new Counter();
Adder adder = new Adder(counter);
Thread t1 = new Thread(adder);
Thread t2 = new Thread(adder);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(counter.getCount());
}
}
I would expect the output of this to be 200, but it's not deterministic (theoretically, can have any value between 0-200). I suspect the problems is that I am using the getter and setter inline, i.e.
counter.setCount(counter.getCount()+1);
For some reason this "breaks" the mutual exclusion that I am trying to achieve with synchronization, but I can't see why.
I implemented the 1's addition with count++ like so:
public synchronized void add1(){
count++;
}
This worked, maybe because this way I use only one function instead of two inline. Could you explain why the first implementation doesn't work?
Calling the getter and subsequent calling of setter is two independent operations. "Set the result of getter plus one" is not atomic here. So you may perfectly have two gets returning the same value, and two sets of the same value increased by one.
Assume count is 100. You have two threads calls calling the getter, both getting 100. Then they both call the setter, setting 101. So the counter is now 101, not 102 - and both threads "were there" already.
So the result is non-deterministic and depends on the actual order of get/set operations from the two threads.
counter.setCount(counter.getCount()+1); is NOT atomic and it involves 3 steps:
(1) Read the value of count
(2) Add one to count
(3) Write the value of count
In the first approach, you are getting the locks independently i.e., in between the get and set calls of one thread there will be an interference of other threads. So you can't guarantee that the first thread read value is the same as when it comes for the writing.
In the second approach, you are holding the lock and performing all of the above 3 steps, so you will not find any problem.
Also, you can also solve your problem by using the threadsafe AtomicInteger class.

Is this synchronized block need?

Is the synchronized block on System.out.println(number); need the following code?
import java.util.concurrent.CountDownLatch;
public class Main {
private static final Object LOCK = new Object();
private static long number = 0L;
public static void main(String[] args) throws InterruptedException {
CountDownLatch doneSignal = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
Worker worker = new Worker(doneSignal);
worker.start();
}
doneSignal.await();
synchronized (LOCK) { // Is this synchronized block need?
System.out.println(number);
}
}
private static class Worker extends Thread {
private final CountDownLatch doneSignal;
private Worker(CountDownLatch doneSignal) {
this.doneSignal = doneSignal;
}
#Override
public void run() {
synchronized (LOCK) {
number += 1;
}
doneSignal.countDown();
}
}
}
I think it's need because there is a possibility to read the cached value.
But some person say that:
It's unnecessary.
Because when the main thread reads the variable number, all of worker thread has done the write operation in memory of variable number.
doneSignal.await() is a blocking call, so your main() will only proceed when all your Worker threads have called doneSignal.countDown(), making it reach 0, which is what makes the await() method return.
There is no point adding that synchronized block before the System.out.println(), all your threads are already done at that point.
Consider using an AtomicInteger for number instead of synchronizing against a lock to call += 1.
It is not necessary:
CountDownLatch doneSignal = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
Worker worker = new Worker(doneSignal);
worker.start();
}
doneSignal.await();
// here the only thread running is the main thread
Just before dying each thread countDown the countDownLatch
#Override
public void run() {
synchronized (LOCK) {
number += 1;
}
doneSignal.countDown();
}
Only when the 10 thread finish their job the doneSignal.await(); line will be surpass.
It is not necessary because you are waiting for "done" signal. That flush memory in a way that all values from the waited thread become visible to main thread.
However you can test that easily, make inside the run method a computation that takes several (millions) steps and don't get optimized by the compiler, if you see a value different than from the final value that you expect then your final value was not already visible to main thread. Of course here the critical part is to make sure the computation doesn't get optimized so a simple "increment" is likely to get optimized. This in general is usefull to test concurrency where you are not sure if you have correct memory barriers so it may turn usefull to you later.
synchronized is not needed around System.out.println(number);, but not because the PrintWriter.println() implementations are internally synchronized or because by the time doneSignal.await() unblocks all the worker threads have finished.
synchronized is not needed because there's a happens-before edge between everything before each call to doneSignal.countDown and the completion of doneSignal.await(). This guarantees that you'll successfully see the correct value of number.
Needed
No.
However, as there is no (documented) guarantee that there will not be any interleaving it is possible to find log entries interleaved.
System.out.println("ABC");
System.out.println("123");
could print:
AB1
23C
Worthwhile
Almost certainly not. Most JVMs will implement println with a lock open JDK does.
Edge case
As suggested by #DimitarDimitrov, there is one further possible use for that lock and it is to ensure a memory barrier is crossed befor accessing number. If that is the concern then you do not need to lock, all you need to do is make number volatile.
private static volatile long number = 0L;

How could the two threads enter the synchronized block at the same time?

There is some weird thing happening. As I enter the synchronized block,I try to print the name of the Thread.After the print statement,I make a husge pause of 100000 seconds.
#Override
public int getNextAvailableVm() {
synchronized(this) {
System.out.println(Thread.currentThread().getName());
try {Thread.sleep(100000000);}catch(Exception exc){}
String dataCenter = dcc.getDataCenterName();
int totalVMs = Temp_Algo_Static_Var.vmCountMap.get(dataCenter);
AlgoHelper ah = (AlgoHelper)Temp_Algo_Static_Var.map.get(dataCenter);
.
.
.
}
}
But as this method is run,name oft the 2 threads are printed.
Thread-11
Thread-13
and it is after this that the long pause occurs. Why is that ? How could the two threads enter the synchronized block,when the first thread has yet not left the block ?
If the two threads are running against the same object then this should not happen.
I would therefore suggest that you are creating a new object for each thread or at least some of the threads are running on different objects.
If you do want multiple objects then you should not use synchronized(this), you should create a static final Object to synchronize on. Please do not sync on this.getClass() as that breaks.
Most likely you are invoking getNextAvailableVm() on different instances of the containing class. Since you are synchronizing on this you will be locking on two different monitors (first thread locks on instance1, second one on instance2).
There are a lot of ways you could correct this:
make the whole method synchronized
synchronize on this.getClass()
define a static object to lock on
use methods from java.util.concurrent.locks to do the locking
These are just some suggestions to address your problem, but to find the right one we would have to know more about your application structure and your requirements.
I guess the below prog, will work like you expected,
Locked on Thread1.Class, Two thread will not execute the method simultaneously
public class Test {
public static void main(String [] args) {
Thread1 t1 = new Thread1();
Thread1 t2 = new Thread1();
t1.start();
t2.start();
}
}
class Thread1 extends Thread{
public void run(){
getNextAvailableVm();
}
public void getNextAvailableVm() {
synchronized(Thread1.class) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
}catch(Exception exc){}
System.out.println(Thread.currentThread().getName());
}
}
}
OUTPUT
Thread-1
Thread-1
Thread-0
Thread-0

Categories

Resources