Synchronized method does not work as expected - java

I have a variable which is shared by two threads. The two threads will do some operations on it. I don't know why the result of sharedVar is different every time I execute the program.
public class Main
{
public static int sharedVar = 0;
public static void main(String[] args)
{
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
mt1.start();
mt2.start();
try
{
// wait for the threads
mt1.join();
mt2.join();
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
System.out.println(sharedInt); // I expect this value to be 20000, but it's not
}
}
The following is the class "MyThread"
public class MyThread extends Thread
{
private int times = 10000;
private synchronized void addOne()
{
for (int i = 0; i < times; ++i)
{
Main.sharedVar ++;
}
}
#Override
public void run()
{
addOne();
}
}
The final result of sharedVar sometimes are 13735, 12508, or 18793; but never 20000, which is the result I expect. Another interesting thing about the program is when times=1000. I always get 2000 as the final result.
Can anyone explain this phenomenon?

A synchronized method protects the resource this that means that your code is equivalent to:
private void addOne()
{
synchronized(this)
{
for (int i = 0; i < times; ++i)
{
Main.sharedVar ++;
}
}
}
But you have 2 objects for which addOne method is called. That means this for mt1.addOne is not the same than this for mt2.addOne and therefore you don't have a common resource of synchronization.
Try changing yout addOne code to:
private void addOne()
{
synchronized(MyThread.class)
{
for (int i = 0; i < times; ++i)
{
Main.sharedVar ++;
}
}
}
And you will observe the expected behaviour. As the comments below suggest, it is better to use a different object than MyThread.class for synchronization since class objects are accesible from many points and it is easy that other code may try to synchronize using the same object.

When you use synchronized on non-static method, you use current object as monitor.
When you use synchronized on static method, you use current object of class (ClassName.class static field) as monitor.
In your case, you use synchronized on Thread's object (2 different instances), so two different threads will modify your sharedVar static field at same time.
You can fix it in different ways.
Move addOne method to Main and make it static.
private static synchronized void addOne(int times)
{
for (int i = 0; i < times; ++i)
{
sharedVar++;
}
}
Or you can create class called SharedVar with field private int var; and method synchronized void addOne(int times) and pass single instance of SharedVar to your treads.
public static void main(String[] args)
{
SharedVar var = new SharedVar();
MyThread mt1 = new MyThread(var);
MyThread mt2 = new MyThread(var);
mt1.start();
mt2.start();
try
{
// wait for the threads
mt1.join();
mt2.join();
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
System.out.println(var.getVar()); // I expect this value to be 20000, but it's not
}
But if you need only one integer to be changed in multiple threads, you can use classes from java.til.concurrent.*, like AtomicLong or AtomicInteger.

Define sharedVar as an AtomicLong instead of int. Making the function synchronized works as well but it is less efficient because you only need the increment to be synchronized.

When a thread is about to execute a 'synchronized' instance method, it aqcuires the lock on the Object(to be precise, lock on that object monitor).
So in your case, Thread mt1 acquires lock on Object mt1 and Thread mt2 acquires lock on Object mt2 and they do not block each Other as the two threads are working on two different locks.
And when two threads modify a shared variable concurrently(not synchronized way), the result is unpredictable.
Well about the case of value 1000, for smaller inputs the interleaved execution might have resulted in correct result(luckily).
Sol : remove the synchronized keyword from addOne method and make sharedVal as type of 'AtomicInteger'

Join the thread immediately after start method. From this thread-1 will start and go to dead state after that thread-2 will start and go to dead state. So it will print your expected output always.
Change the code as shown below:-
public class Main{
public static int sharedVar = 0;
public static void main(String[] args)
{
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
try
{
mt1.start();
mt1.join();
mt2.start();
mt2.join();
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
System.out.println(sharedVar);
}
}
class MyThread extends Thread
{
private int times = 1000000;
private synchronized void addOne()
{
for (int i = 0; i < times; ++i)
{
Main.sharedVar++;
}
}
#Override
public void run()
{
addOne();
}
}

Related

Solving Counter Problem in Java Thread With synchronized method and block

I just wrote code for counter problem in a thread. When I add synchronized on Method its working fine but when I use synchronized block inside a method it does not work, why? Something I am missing, I guess.
public class CounterProblem {
class Counter implements Runnable {
private Integer count = 0;
#Override
public void run() {
for(int i = 0; i < 10000; i++) {
increment();
}
}
// THIS GIVES 20000 which is correct every time.
public synchronized void increment() {
count++;
}
// THIS GIVES wrong every time. WHY ?
// public void increment() {
// synchronized(count) {
// count++;
// }
// }
}
public static void main(String[] args) throws InterruptedException {
CounterProblem counterProblem = new CounterProblem();
Counter counter = counterProblem.new Counter();
Thread thread1 = new Thread(counter);
Thread thread2 = new Thread(counter);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(counter.count);
}
}
java.lang.Integer's aren't mutable. When you increment an Integer, you unbox it to a primitive int, increment it, and then autobox the result to a different Integer instance. This means your synchronized block synchronizes on a different object every time, making it pointless - as you've seen yourself.

Alternate between two threads (producer-consumer)

I'm attempting to edit my program so that the incrementer and decrementer classes are called alternatively, which incrementer being performed first. My aim is to be able to print the value of a shared variable (sharedValue) after each increment/decrement and hopefully see it toggle between 1 and 0. Below is the code for my main class, a semaphore class and incrementer class (there is a class decrementer which is styled the same way as icrementer so i didn't include it).
main class
public class Main extends Thread {
private static int sharedValue = 0;
private static Semaphore semaphore = new Semaphore(1);
static int numberOfCycles = 20000;
public static void increment() {
semaphore.down();
sharedValue++;
semaphore.up();
}
public static void decrement() {
semaphore.down();
sharedValue--;
semaphore.up();
}
public static void main(String[] args) throws InterruptedException {
incrementer inc = new incrementer(numberOfCycles);
inc.start();
inc.join();
decrementer dec = new decrementer(numberOfCycles);
dec.start();
dec.join();
System.out.println(sharedValue);
}
}
Semaphore class
private int count;
// Constructor
public Semaphore(int n) {
count = n;
}
// Only the standard up and down operators are allowed.
public synchronized void down() {
while (count == 0) {
try {
wait(); // Blocking call.
} catch (InterruptedException exception) {
}
}
count--;
}
public synchronized void up() {
count++;
notify();
}
incrementer Class
public class incrementer extends Thread{
private int numberOfIncrements;
public incrementer(int numOfIncrements){
numberOfIncrements = numOfIncrements;
}
public void run(){
for(int i = 0; i <= numberOfIncrements; i++){
Main.increment();
}
}
}
Thanks in advance!
So I have been reading through my notes and it occurred to me that I could use another mutex semaphore which can determine if the buffer is full or empty. Am I right with this approach?
Thread.Join causes your main thread to wait for the completion of the incrementer, then starts the decrementer and then waits for decrementer to complete. If you want them to run concurrently, remove the two Thread.Join calls:
public static void main(String[] args) throws InterruptedException {
incrementer inc = new incrementer(numberOfCycles);
decrementer dec = new decrementer(numberOfCycles);
inc.start();
dec.start();
}
To print the shared value after each increment or decrement, move the println call to the increment and decrement functions of your main class:
public static void increment() {
semaphore.down();
sharedValue++;
System.out.println(sharedValue);
semaphore.up();
}
public static void decrement() {
semaphore.down();
sharedValue--;
System.out.println(sharedValue);
semaphore.up();
}
Also note that even with these changes you won't be observing the toggling between 1 and 0. This is because the two threads don't start at the same time, and even if they did (e.g. using CyclicBarrier) you can't control the scheduling so they would progress differently. If you really want to observe this output, you should make each thread wait for 1ms before and after calling semaphore.up() in order to give the other thread a chance to wait and acquire a permit from the semaphore.
public static void increment() {
semaphore.down();
sharedValue++;
System.out.println(sharedValue);
try {
Thread.sleep(1); //give time to other threads to wait for permit
semaphore.up();
Thread.sleep(1); //give time to other threads to acquire permit
} catch (InterruptedException ex) {
}
}
There are more robust ways to get this kind of output from two threads, but I didn't want to make major modifications to your code.

Java Multithreading - Threadsafe Counter

I'm starting off with a very simple example in multithreading. I'm trying to make a threadsafe counter. I want to create two threads that increment the counter intermittently to reach 1000. Code below:
public class ThreadsExample implements Runnable {
static int counter = 1; // a global counter
public ThreadsExample() {
}
static synchronized void incrementCounter() {
System.out.println(Thread.currentThread().getName() + ": " + counter);
counter++;
}
#Override
public void run() {
while(counter<1000){
incrementCounter();
}
}
public static void main(String[] args) {
ThreadsExample te = new ThreadsExample();
Thread thread1 = new Thread(te);
Thread thread2 = new Thread(te);
thread1.start();
thread2.start();
}
}
From what I can tell, the while loop right now means that only the first thread has access to the counter until it reaches 1000. Output:
Thread-0: 1
.
.
.
Thread-0: 999
Thread-1: 1000
How do I fix that? How can I get the threads to share the counter?
You could use the AtomicInteger. It is a class that can be incremented atomically, so two seperate threads calling its increment method do not interleave.
public class ThreadsExample implements Runnable {
static AtomicInteger counter = new AtomicInteger(1); // a global counter
public ThreadsExample() {
}
static void incrementCounter() {
System.out.println(Thread.currentThread().getName() + ": " + counter.getAndIncrement());
}
#Override
public void run() {
while(counter.get() < 1000){
incrementCounter();
}
}
public static void main(String[] args) {
ThreadsExample te = new ThreadsExample();
Thread thread1 = new Thread(te);
Thread thread2 = new Thread(te);
thread1.start();
thread2.start();
}
}
Both threads have access to your variable.
The phenomenon you are seeing is called thread starvation. Upon entering the guarded portion of your code (sorry I missed this earlier), other threads will need to block until the thread holding the monitor is done (i.e. when the monitor is released). Whilst one may expect the current thread pass the monitor to the next thread waiting in line, for synchronized blocks, java does not guarantee any fairness or ordering policy to which thread next recieves the monitor. It is entirely possible (and even likely) for a thread that releases and attempts to reacquire the monitor to get hold of it over another thread that has been waiting for a while.
From Oracle:
Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads. For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked.
Whilst both of your threads are examples of "greedy" threads (since they repeatedly release and reacquire the monitor), thread-0 is technically started first, thus starving thread-1.
The solution is to use a concurrent synchronization method that supports fairness (e.g. ReentrantLock) as shown below:
public class ThreadsExample implements Runnable {
static int counter = 1; // a global counter
static ReentrantLock counterLock = new ReentrantLock(true); // enable fairness policy
static void incrementCounter(){
counterLock.lock();
// Always good practice to enclose locks in a try-finally block
try{
System.out.println(Thread.currentThread().getName() + ": " + counter);
counter++;
}finally{
counterLock.unlock();
}
}
#Override
public void run() {
while(counter<1000){
incrementCounter();
}
}
public static void main(String[] args) {
ThreadsExample te = new ThreadsExample();
Thread thread1 = new Thread(te);
Thread thread2 = new Thread(te);
thread1.start();
thread2.start();
}
}
note the removal of the synchronized keyword in favor of the ReentrantLock within the method. Such a system, with a fairness policy, allows long waiting threads a chance to execute, removing the starvation.
Well, with your code I don't know how to get "exactly" intermittently, but if you use Thread.yield() after call incrementCounter() you will have a better distribution.
public void run() {
while(counter<1000){
incrementCounter();
Thread.yield();
}
}
Otherwise, to get what you propose, you can create two different thread class (ThreadsExample1 and ThreadsExample2 if you want), and another class to be a shared variable.
public class SharedVariable {
private int value;
private boolean turn; //false = ThreadsExample1 --> true = ThreadsExample2
public SharedVariable (){
this.value = 0;
this.turn = false;
}
public void set (int v){
this.value = v;
}
public int get (){
return this.value;
}
public void inc (){
this.value++;
}
public void shiftTurn(){
if (this.turn){
this.turn=false;
}else{
this.turn=true;
}
}
public boolean getTurn(){
return this.turn;
}
}
Now, the main can be:
public static void main(String[] args) {
SharedVariable vCom = new SharedVariable();
ThreadsExample1 hThread1 = new ThreadsExample1 (vCom);
ThreadsExample2 hThread2 = new ThreadsExample2 (vCom);
hThread1.start();
hThread2.start();
try {
hThread1.join();
hThread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
And you have to change your line static int counter = 1; // a global counter
for private SharedVariable counter;
And the new run is:
public void run() {
for (int i = 0; i < 20; i++) {
while (!counter.getTurno()){
Thread.yield();
}
System.out.println(this.counter.get());
this.counter.cambioTurno();
}
}
}
Yes, it is another code, but I think it can help you a little bit.

Thread output inconsistent even when using synchronized keyword

I am very new to threads. I wrote a code and expected my output as 20000 consistently. But that's not the case. Please find the code below:
class Runner4 implements Runnable {
static int count = 0;
public synchronized void increase() {
count++;
}
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
increase();
}
}
}
public class threading4 {
public static void main(String[] args) {
Thread t1 = new Thread(new Runner4());
t1.start();
Thread t2 = new Thread(new Runner4());
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Runner4.count);
}
}
Any explanation?
Thanks!!
You are synchronizing on two different objects in your code (corresponding to the two objects you created). As such, there is no protection of the shared static variable, and you get unpredictable results. Basically, there is no effective synchronization going on in your program. You can fix this with a simple modification.
Change:
public synchronized void increase(){
count++;
}
To:
public void increase(){
synchronized(Runner4.class) {
count++;
}
}
Note that I am not saying this is the best way to accomplish this kind of synchronization - but the important take-away is that, if you are modifying a class level variable, you need class level synchronization as well.
Your code would work if count was not static.
public synchronized void increase() {
// method body
}
is equivalent to
public void increase() {
synchronized(this) {
// method body
}
}
Since count is static, both t1 and t2 are accessing it with different locks, resulting in non-deterministic behavior. Either make Runner4.increase synchronize on a common lock (Runner4.class or a private static lock object would work just fine), or make count non-static.
The way you're trying to achieve what you want is is not really the best way.
A better way to do it is define a class called Counter, as the following:
public class Counter
{
int count;
public Counter()
{
count = 0;
}
public synchronized void increase() {
count++;
}
public int getCount()
{
return count;
}
}
The class has the methods of increasing the counter and getting it.
What you need to do now is have a Counter object to be shared by two threads that call the increase() method. So your thread class would look like this:
class Runner4 extends Thread {
Counter count;
public Runner4(Counter c)
{
count = c;
}
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
count.increase();
}
}
}
Notice that the class takes a Counter object and calls the increase method. Also the class extends Thread instead of implementing Runnable. There is really no much difference, it's just now your Runner4 can use Thread class methods.
From your main defines a Counter object and two Runner4 threads, and then pass the Counter object to each one of them:
public static void main(String[] args) {
Counter count = new Counter();
Thread t1 = new Runner4(count);
t1.start();
Thread t2 = new Runner4(count);
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(count.getCount());
}

IlleagalMonitorStateException when I am trying to run this program

public class ThreadTest
{
public static Integer i = new Integer(0);
public static void main(String[] args) throws InterruptedException
{
ThreadTest threadTest = new ThreadTest();
Runnable odd = threadTest.new Numbers(1, "thread1");
Runnable even = threadTest.new Numbers(0, "thread2");
((Thread) odd).start();
((Thread) even).start();
}
class Numbers extends Thread
{
int reminder;
String threadName;
Numbers(int reminder, String threadName)
{
this.reminder = reminder;
this.threadName = threadName;
}
#Override
public void run()
{
while (i < 20)
{
synchronized (i)
{
if (i % 2 == reminder)
{
System.out.println(threadName + " : " + i);
i++;
i.notify();
}
else
{
try
{
i.wait();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
}
You can't synchronize on i because it changes during execution of your program.
Since Integer in Java is immutable, after executing i++ i will contain a reference to another object, not the object you have synchronized on. So, you can't call wait()/notify() on this new object, because these methods may be only called on the object you are synchronized on, otherwise you get IllegalMonitorStateException.
You need to synchronize on some other object that doesn't change during execution. For example, you may create a separate object for this purpose:
public class ThreadTest {
public static Integer i = new Integer(0);
public static Object lock = new Object();
...
class Numbers extends Thread {
...
#Override
public void run() {
...
synchronized (lock) {
...
lock.notify();
...
lock.wait();
...
}
}
}
}
This line:
i++;
is equivalent to:
i = i + 1;
which (due to autoboxing) becomes something like:
i = new Integer(i.intValue() + 1);
So, when you call i.notify() you are synchronized on the old i, not the new one.
I'd suggest changing i into an ordinary int variable, and create a separate object to synchronize on:
static int i = 0;
static Object iMonitor = new Object();
As documentation states the exception is thrown when
the current thread is not the owner of the object's monitor
It also states that
This method should only be called by a thread that is the owner of this object's monitor.
And this condition can be obtained by
By executing a synchronized instance method of that object.
By executing the body of a synchronized statement that synchronizes on the object.
For objects of type Class, by executing a synchronized static method of that class.
You could try calling the wait method from inside the class that uses i. This could be done by extending the class and writing two new methods for notify and wait..
You cannot put wait() and notify() in the same synchronized block because that will just cause a deadlock. Make sure only the wait and notify functions are wrapped with a synchronized block like this:
synchronized (i) {
i.wait(); // or i.notify();
}

Categories

Resources