I can't Seem to get a final counter value Of 20000. What is wrong with this code?
public class Synchronize2 {
public static void main(String[] args) {
Threading t1 = new Threading();
Threading t2 = new Threading();
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Threading.counter);
}
}
class Threading extends Thread {
static int counter;
public synchronized void incrementer() {
counter++;
}
public void run() {
for (int i=0; i<10000; i++) {
incrementer();
}
}
}
Your synchronized incrementer method will lock on the object itself. But you have 2 different objects, each locking on themselves, so the method isn't thread safe; both threads can still access incrementer at the same time.
Additionally, the post-increment operation isn't thread safe because it's not atomic; there is a read operation and an increment operation, and a thread can be interrupted in the middle of the two operations. This non-thread-safe code presents a race condition, where thread one reads the value, thread two reads the value, then thread one increments and thread two increments, yet only the last increment "wins" and one increment is lost. This shows up when the ending value is less than 20000.
Make the method static too, so that because it's synchronized, it will lock on the class object of the class, which is proper synchronization here.
public static synchronized void incrementer() {
You synchronize on two different Objects. Your incrementer is a short form of this:
public void incrementer() {
synchronized (this) {
counter++;
}
}
But the two instances of "this" are not the same Object. Thus, you do not synchronize at all. Try it this way:
private static Object sync = new Object();
public void incrementer() {
synchronized (sync) {
counter++;
}
}
You should also make the variable counter volatile. It is not strictly neccessary here, because you use it only in synchronized blocks. But in real code you might read it outside such a block, and then you will get problems. Non volatile variables can be read from a local thread cache, instead from the memory.
Related
This question already has answers here:
Why is i++ not atomic?
(10 answers)
Closed 6 years ago.
Java MultiThreading skips loop and gives wrong result
package Threading;
class DemoThread extends Thread{ //Thread Class
static int count=0; // variable incremented by both the threads
public DemoThread(String name) {
// TODO Auto-generated constructor stub
super(name);
}
public void run() {
for(int i=0;i<100000;i++) {
count++;
System.out.println(Thread.currentThread()+"Count"+count); // print thread operating on count variable
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class MyThreadClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
DemoThread t1=new DemoThread("T1");
DemoThread t2=new DemoThread("T2");
t1.start();
t2.start();
try {
t1.join();
t2.join(); //allowing both the threads to complee before main thread
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Main Thread ends"+DemoThread.count); //final value of count
}
}
The final value of count should be 199998 but it is not giving the desired result.
Why the threads are missing the loops ???
It happened because Thread T1 and T2 will update count at the same time (concurrency) like that:
Thread[T1,5,main]Count10
Thread[T2,5,main]Count10
Thread[T1,5,main]Count12
Thread[T2,5,main]Count12
Thread[T2,5,main]Count14
Thread[T1,5,main]Count14
Thread[T1,5,main]Count15
Thread[T2,5,main]Count16
You should use AtomicInteger
And update your code:
static int count=0; to static AtomicInteger count= new AtomicInteger();
count++; to count.incrementAndGet();
You must use java.util.concurrent.atomic.AtomicInteger and not a shared static int variable.
Problem
In Java, multi threading introduces asynchronous behavior to your programs, you must enforce synchronicity when you need it.
Without synchronization, nothing stops a thread to access from calling a same method, on same object at the same time. This is known as Race Condition, because threads are racing each other to complete the method.
The output to your program:
The first line of the output printed 2!? This is because t1 wrote count's value and was preempted before it could print it. Note that for a thread to be preempted it need not go into sleep. OS does this neverthless.
If you notice the 1st line and 4th line you can see the inconsistency. This kind of inconsistency becomes unpredictable in huge programs.
Here are end results for running multiple times.
It should not be taken granted that always wrong results are produced. No, sometimes correct results are produced. It means that results will be unpredictable.
Misunderstanding on?
Thread skipped loop.!? No, thread didn't skip loop. Different threads accessed same value but before it could write it's own value other thread wrote the value and proceeded. As a result the next time it accessed the value, it picked up the wrong value.
This is known as Reader Writer Problem
Solution
In your program, t1 and t2 are accessing your count variable with different values. To prevent other threads from calling run() before other thread completes it we add a synchronized keyword before the method.
synchronized public void run(){}
The synchronized keyword guards the state from race conditions. Once, a thread enters the synchronized method, other threads are not allowed to use the method until the previous thread exits the method.
Here is the correct output due to synchronized keyword.
Note: I used 200 as the end for loop.
Bonus
If there are proprietary methods you are using which take in shared data as input. You can use synchronized block
synchronized(objRef){
//Method calling
}
objRef is the reference of the object being synchronized.
As recommended in comments
[Recommended Solution]
You should use AtomicInteger instead of native int. Use java.util.concurrent.atomic package.
Reference to java.util.concurrent.atomic
Instead of static int count = 0; use static AtomicInteger count = new AtomicInteger(0); and instead of count++; use count.incrementAndGet();
AtomicInteger is inherently synchronized.
Atomic Integer Reference Java Docs
There might be a straightforward for this issue, but I am not understanding the concept here.
I am trying a simple program where I am having 3 threads executing a synchronized block to print letter in an incrementing order.The synchronized block is having lock on the variable(which is a StringBuffer object). Below is the code:
public class SimpleThread extends Thread implements Runnable{
private StringBuffer myBuffer;
public StringBuffer getMyBuffer() {
return myBuffer;
}
public void setMyBuffer(StringBuffer myBuffer) {
this.myBuffer = myBuffer;
}
public SimpleThread(StringBuffer myBuffer) {
this.myBuffer = myBuffer;
}
public void run() {
synchronized (this.myBuffer) {
while((int)(this.myBuffer.charAt(0))!=68) {
for(int i=0;i<3;i++) {
System.out.println(this.myBuffer.charAt(0));
}
char x = this.myBuffer.charAt(0);
this.myBuffer.setCharAt(0, (char) (x+1));
}
//this.myBuffer.setCharAt(0, 'A');
}
}
public static void main(String[] args) {
StringBuffer safeBuffer = new StringBuffer();
safeBuffer.append('A');
SimpleThread one = new SimpleThread(safeBuffer);
one.setName("One");
one.start();
SimpleThread two = new SimpleThread(safeBuffer);
two.setName("Two");
two.start();
SimpleThread three = new SimpleThread(safeBuffer);
three.setName("Three");
three.start();
}
Output for the program is:
A
A
A
B
B
B
C
C
C
It is only printing the value when thread One is executing and for other two threads, the of variable myBuffer is becoming D. What I don't understand is why changing the variable for one object reflect for other objects?
synchronized means only one thread can execute the code block at a time. You might be confusing the wording to think it synchronizes the variable.
When you write synchronized (this.myBuffer), you are telling the program to use myBuffer as a lock when deciding if a thread can execute the following code block.
This means when a thread tries to execute synchronized (this.myBuffer) { } it will attempt to get the lock on myBuffer.
If no other thread has the lock, it will obtain it and execute the
code block.
If another thread has the lock it will wait until the other thread releases the lock (usually by finishing running the code inside the code block).
That means all threads will always take turns executing the contents of synchronized (this.myBuffer) { }.
Since thread "One" is started first, it will get the lock first and finish all the work it has thus incrementing the myBuffer content to D, before handing it over to thread "Two".
This question already has answers here:
Why is i++ not atomic?
(10 answers)
Closed 6 years ago.
Java MultiThreading skips loop and gives wrong result
package Threading;
class DemoThread extends Thread{ //Thread Class
static int count=0; // variable incremented by both the threads
public DemoThread(String name) {
// TODO Auto-generated constructor stub
super(name);
}
public void run() {
for(int i=0;i<100000;i++) {
count++;
System.out.println(Thread.currentThread()+"Count"+count); // print thread operating on count variable
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class MyThreadClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
DemoThread t1=new DemoThread("T1");
DemoThread t2=new DemoThread("T2");
t1.start();
t2.start();
try {
t1.join();
t2.join(); //allowing both the threads to complee before main thread
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Main Thread ends"+DemoThread.count); //final value of count
}
}
The final value of count should be 199998 but it is not giving the desired result.
Why the threads are missing the loops ???
It happened because Thread T1 and T2 will update count at the same time (concurrency) like that:
Thread[T1,5,main]Count10
Thread[T2,5,main]Count10
Thread[T1,5,main]Count12
Thread[T2,5,main]Count12
Thread[T2,5,main]Count14
Thread[T1,5,main]Count14
Thread[T1,5,main]Count15
Thread[T2,5,main]Count16
You should use AtomicInteger
And update your code:
static int count=0; to static AtomicInteger count= new AtomicInteger();
count++; to count.incrementAndGet();
You must use java.util.concurrent.atomic.AtomicInteger and not a shared static int variable.
Problem
In Java, multi threading introduces asynchronous behavior to your programs, you must enforce synchronicity when you need it.
Without synchronization, nothing stops a thread to access from calling a same method, on same object at the same time. This is known as Race Condition, because threads are racing each other to complete the method.
The output to your program:
The first line of the output printed 2!? This is because t1 wrote count's value and was preempted before it could print it. Note that for a thread to be preempted it need not go into sleep. OS does this neverthless.
If you notice the 1st line and 4th line you can see the inconsistency. This kind of inconsistency becomes unpredictable in huge programs.
Here are end results for running multiple times.
It should not be taken granted that always wrong results are produced. No, sometimes correct results are produced. It means that results will be unpredictable.
Misunderstanding on?
Thread skipped loop.!? No, thread didn't skip loop. Different threads accessed same value but before it could write it's own value other thread wrote the value and proceeded. As a result the next time it accessed the value, it picked up the wrong value.
This is known as Reader Writer Problem
Solution
In your program, t1 and t2 are accessing your count variable with different values. To prevent other threads from calling run() before other thread completes it we add a synchronized keyword before the method.
synchronized public void run(){}
The synchronized keyword guards the state from race conditions. Once, a thread enters the synchronized method, other threads are not allowed to use the method until the previous thread exits the method.
Here is the correct output due to synchronized keyword.
Note: I used 200 as the end for loop.
Bonus
If there are proprietary methods you are using which take in shared data as input. You can use synchronized block
synchronized(objRef){
//Method calling
}
objRef is the reference of the object being synchronized.
As recommended in comments
[Recommended Solution]
You should use AtomicInteger instead of native int. Use java.util.concurrent.atomic package.
Reference to java.util.concurrent.atomic
Instead of static int count = 0; use static AtomicInteger count = new AtomicInteger(0); and instead of count++; use count.incrementAndGet();
AtomicInteger is inherently synchronized.
Atomic Integer Reference Java Docs
class Call {
int count;
public void increment() {
for (int i = 0; i < 1000; i++)
count++;
}
}
class Caller implements Runnable {
Call c;
public Caller(Call c) {
this.c = c;
}
#Override
public void run() {
// TODO Auto-generated method stub
c.increment();
}
}
class Calling implements Runnable {
Call c;
public Calling(Call c) {
this.c = c;
}
#Override
public void run() {
// TODO Auto-generated method stub
synchronized (c) {
c.increment();
}
}
}
public class SynchronizedBlock {
public static void main(String[] args) throws InterruptedException {
Call call = new Call();
Calling calling = new Calling(call);
Caller caller = new Caller(call);
Thread t1 = new Thread(caller);
Thread t2 = new Thread(calling);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("caller:" + caller.c.count);
}
}
Here have made increment method synchronized in 1 class and in other class i havent made it as synchronized. When i run the above code , it sometimes gives value of count less than 2000 .
As per my understanding, Since Calling class's object has already locked the object, so there is no need to synchronize in Caller class increment method.
Could you please help me in understanding the logic here.
Since Calling class's object has already locked the object, so there
is no need to synchronize in Caller class increment method.
Your understanding is incorrect. In order for parallel actions on a variable to be deterministic, you must have some sort of synchronization in place on every access/modification to that variable**.
You need to synchronize in Caller as well.
**: This is a necessary but insufficient condition to guarantee determinism.
synchronized keyword in java means that lock will be acquired before entering the block and released after exit.
Since t2 acquires/releases the lock and t1 doesn't, there is effectively no synchronization going on. t1 just goes in the block whenever the CPU time is assigned to it.
t2 also always goes in the block without waiting because the lock is never acquired by t1.
--
If you synchronize the increment method your program will work correctly:
class Call {
int count;
public synchronized void increment() {
for (int i = 0; i < 1000; i++)
count++;
}
}
After this change you can remove the synchronized block from t2.
What's probably happening when you get the correct value of 2000, happens between the lines:
t1.start();
t2.start();
This is because the execution of public void increment(); is finishing in a single quantum, before the t2.start() line is even executed. A Thread Quantum is the time that the thread runs before a different thread can run on the processors core.
The first thread doesn't lock the object, and occasionally a single quantum will not encompass the entire execution of increment(), which leaves time for thread 2 to begin executing and working on the same object data. This will result in 2 copies of the variable count existing at the same time, competing for the same memory.
Try increasing the amount of increments for (int i = 0; i < 1000; i++) to some number like for (int i = 0; i < 10000000; i++). You will most likely see the application begin to fail more often.
I am trying to understand Synchornized in Java.
I understood if I have access a synchronized method on same object from 2 different Threads, only one will be able to access at a time.
But I think if the same method is being called on 2 different instances, Both Objects should be able to access the method parallel. Which would cause race condition if accessing/modifying a static member variable from the method. But I am not able to see the race condition happening in below code.
Could someone please explain whats wrong with the code or my understanding.
For reference code is accessible at : http://ideone.com/wo6h4R
class MyClass
{
public static int count=0;
public int getCount()
{
System.out.println("Inside getcount()");
return count;
}
public synchronized void incrementCount()
{
count=count+1;
}
}
class Ideone
{
public static void main(String[] args) throws InterruptedException {
final MyClass test1 = new MyClass();
final MyClass test2 = new MyClass();
Thread t1 = new Thread() {
public void run()
{
int k=0;
while (k++<50000000)
{
test1.incrementCount();
}
}
};
Thread t2 = new Thread() {
public void run()
{
int l=0;
while (l++<50000000)
{
test2.incrementCount();
}
}
};
t1.start();
t2.start();
t1.join();
t2.join();
//System.out.println(t2.getState());
int x=500000000+500000000;
System.out.println(x);
System.out.println("count = " + MyClass.count);
}
}
You're right that the race condition exists. But the racy operations are so quick that they're unlikely to happen -- and the synchronized keywords are likely providing synchronization "help" that, while not required by the JLS, hide the races.
If you want to make it a bit more obvious, you can "spell out" the count = count + 1 code and put in a sleep:
public synchronized void incrementCount()
{
int tmp = count + 1;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
count=tmp;
}
That should show the races more easily. (My handling of the interrupted exception is not good for production code, btw; but it's good enough for small test apps like this.)
The lesson learned here is: race conditions can be really hard to catch through testing, so it's best to really understand the code and prove to yourself that it's right.
Since syncrhonized methods actually synchronize on this different instance methods will lock on different objects and therefore you will get race conditions since they don't block each other.
You probably have to make your own lock object and lock on that.
class MyClass
{
public static int count=0;
//this is what you lock on
private static Object lock = new Object();
public int getCount()
{
synchronized(lock){
System.out.println("Inside getcount()");
return count;
}
}
public void incrementCount()
{
synchronized(lock){
count = count+1;
}
}
//etc
Now when you run your main, this gets printed out:
1000000000
count = 100000000
Here's the relevant section of the Java specification:
"A synchronized method acquires a monitor (ยง17.1) before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used."
However I fail to see where the MyClass' instances are actually incrementing "count" so what exactly are you expecting to show as a race condition?
(Taken originally from this answer)