This question already has answers here:
What does 'synchronized' mean?
(17 answers)
Is there an advantage to use a Synchronized Method instead of a Synchronized Block?
(23 answers)
Java synchronized method lock on object, or method?
(11 answers)
Closed 5 years ago.
Below code doesn't give synchronized output.
public class MultiThr implements Runnable{
public static void main(String[] args) {
for(int i = 0;i < 5;i++){
new Thread(new MultiThr()).start();
}
}
#Override
public void run() {
increment();
}
public synchronized void increment(){
for(int i=0;i<10;i++){
System.out.println(i);
try {
Thread.sleep(400);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Could anybody explain me how to get object lock on increment() method?
This usage of the synchronized keyword causes the method to acquire a lock on the object that the method is being invoked on. Since you have 5 MultiThr objects, that's 5 different objects that are being locked.
There are a number of options to fix this, for instance you could create an object that to be shared among all MultiThr objects:
public class MultiThr implements Runnable{
private static final Object lock = new Object();
public static void main(String[] args) {
for(int i = 0;i < 5;i++){
new Thread(new MultiThr()).start();
}
}
#Override
public void run() {
increment();
}
public void increment(){
synchronized (lock) {
for(int i=0;i<10;i++){
System.out.println(i);
try {
Thread.sleep(400);
} catch (InterruptedException e) {}
}
}
}
}
your increment() method is synchronized. Your problem is that it is a part of your Runnable. More of that, your counter variable i is a local variable, so each thread will have it's own copy of i even without the synchronized keyword.
What I would recommend you to do is to create a class MyConter like:
class MyCounter {
private int i;
public MyCounter () {
i = 0;
}
public int getCounter() {
return i;
}
public void increment() {
i++;
}
}
Then pass it as an argument to the MultiThr constructor:
public class MultiThr implements Runnable{
private MyCounter counter;
public MultiThr(MyCounter counter) {
this.counter = counter;
}
#Override
public void run() {
increment();
}
public synchronized void increment(){
for(int i=0;i<10;i++){
counter.increment();
System.out.println(counter.getCounter());
try {
Thread.sleep(400);
} catch (InterruptedException e) {
// Do not do just e.printStackTrace()
Thread.currentThread().interrupt()
}
}
}
public static void main(String[] args) {
for(int i = 0;i < 5;i++){
new Thread(new MultiThr()).start();
}
}
}
Or you can use AtomicInteger instead of MyCounter, just make sure that the same instance is passed to each thread.
Related
so much confused why I get a random result while doing 'i++' in a synchronized or a locked method?
public class aaa implements Runnable {
static int count = 0;
public static void main(String[] args) {
aaa aaa = new aaa();
aaa.create();
}
public void create() {
ExecutorService executor = Executors.newFixedThreadPool(100);
for (int i = 0; i < 1000; i++) {
aaa thread = new aaa();
executor.execute(thread);
}
executor.shutdown();
while (true){
if(executor.isTerminated()){
System.out.println("a " + count);
break;
}
}
}
#Override
public void run() {
this.test();
}
public void test() {
Lock lock = new ReentrantLock();
try {
lock.lock();
count++;
System.out.println(count);
} finally {
lock.unlock();
}
}
}
OR:
public synchronized void test() {
count++;
System.out.println(count);
}
the result is a random number sometimes 1000 sometimes 998, 999 ...etc and the print from inside the 'test' method is not in a sequence, it is like :
867
836
825
824
821
820
819
817
816
a 999
However, if it is in a synchronized block, everything looks good:
public void test() {
synchronized (aaa.class) {
count++;
System.out.println(count);
}
}
the result:
993
994
995
996
997
998
999
1000
a 1000
I think all of the methods above should give me the same result 1000, and the self increment should be in a sequence, but only the last method works.What is wrong with the code? Please help!!!
You are creating multiple instances of aaa, each instance creates its own ReentrantLock, and every thread in execution smoothly acquires a lock from its own instance.
public void test() {
Lock lock = new ReentrantLock();
try {
lock.lock();
count++;
System.out.println(count);
} finally {
lock.unlock();
}
}
Since there are multiple instances of aaa, each thread is running on its own instance and the synchronized method uses current object of aaa.class
public synchronized void test() {
count++;
System.out.println(count);
}
The reason for getting a proper result in this approach is, you are using the aaa.class as an object to the synchronization
public void test() {
synchronized (aaa.class) {
count++;
System.out.println(count);
}
}
The solution is, reuse the same lock(ReentrantLock) across all the threads. Defining the lock in the same level as the variable count would solve the issue.
You must create a single mutex, i.e.
static Lock lock = new ReentrantLock();
Your synchronized method does not work since you are creating N aaa instances then, every (non static) method is different (with their own mutex).
Your synchronized (aaa.class) works since aaa.class is the same Object for all aaa instances and methods.
Then, if you need synchronize the method be sure it is the same for all threads, e.g. if test is static will be the same for all
#Override
public void run() {
test();
}
public static synchronized void test() {
count++;
}
but you can inject a "counter class", e.g.
class Counter {
int count = 0;
// non static but synchronized for all (since they use the same `counter` object)
synchronized void inc() {
count++;
}
}
to be used for all threads
...
SyncTest thread = new SyncTest(counter); // <== the same
...
(full code)
public class SyncTest implements Runnable {
private final Counter c;
public SyncTest(Counter c) {
this.c = c;
}
static class Counter {
int count = 0;
// non static but synchronized for all (since they use the same `counter` object)
synchronized void inc() {
count++;
}
}
#Override
public void run() {
test();
}
public void test() {
this.c.inc();
}
public static void main(String[] args) {
// one counter for all
Counter counter = new Counter();
ExecutorService executor = Executors.newFixedThreadPool(100);
for (int i = 0; i < 10000; i++) {
SyncTest thread = new SyncTest(counter);
executor.execute(thread);
}
executor.shutdown();
while (true) {
if (executor.isTerminated()) {
System.out.println("a " + counter.count);
break;
}
}
}
}
Rule of thumb: Declare your lock variable on the next line after the variable(s) that you want to protect with it, and declare it with the same keywords. E.g.,
public class aaa implements Runnable {
static int count = 0;
static Lock countLock = new ReentrantLock();
...
If you read deeply enough into any of the other answers here, then you will see why this helps.
```
package programs;
public class TestThreads {
public static void main(String[] args) {
ThreadOne t1 = new ThreadOne();
ThreadTwo t2 = new ThreadTwo();
Thread one = new Thread(t1);
Thread two = new Thread(t2);
one.start();
two.start();
}
}
class Accum{
private static Accum a = new Accum();
private int counter = 0;
private Accum() {
}
public static Accum getAccum() {
return a;
}
public void updateCounter(int add) {
counter +=add;
}
public int getCount() {
return counter;
}
}
class ThreadOne implements Runnable{
Accum a = Accum.getAccum();
#Override
public void run() {
for(int x=0;x<98;x++) {
a.updateCounter(1000);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("one "+ a.getCount());
}
}
class ThreadTwo implements Runnable{
Accum a = Accum.getAccum();
#Override
public void run() {
for(int x=0;x<99;x++) {
a.updateCounter(1);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("two "+ a.getCount());
}
}
```
The expected output should be as below
One 98098
Two 98099
But I am getting values same for both One and Two.
Is this expected or both should result in different values?
When it comes to thread priorities eventhough the jvm scheduler takes the role to choose the turn of which thread should execute first, what about the results of this program where two void run programs of for loop with 98 and 99 which should result in two different values else the same
This is because shared data is NOT synchronized.
To resolve this problem, use synchronized on methods those touch the shared data, to make Accum class Thread-Safe.
example:
class Accum{
private static Accum a = new Accum();
private int counter = 0;
private Accum() {
}
public static Accum getAccum() {
return a;
}
public synchronized void updateCounter(int add) {
counter +=add;
}
public synchronized int getCount() {
return counter;
}
}
Maybe make the methods and fields in the Accum class static, because then it is saved in a general place and not an instance...
Code:
class Accum{
private static Accum a = new Accum();
private static int counter = 0;
private Accum() {
}
public static Accum getAccum() {
return a;
}
public static void updateCounter(int add) {
counter +=add;
}
public static int getCount() {
return counter;
}
}
class ThreadTwo implements Runnable{
#Override
public void run() {
for(int x=0;x<99;x++) {
Accum.updateCounter(1);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("two "+ Accum.getCount());
}
}
class ThreadOne implements Runnable{
#Override
public void run() {
for(int x=0;x<98;x++) {
Accum.updateCounter(1000);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("one "+ Accum.getCount());
}
}
I am not very experienced in Java yet, so this might not work...
[EDIT] I tested it and I believe it works
class hehe implements Runnable {
static int count = 0;
public synchronized void count() {
count++;
}
public void run() {
for (int i = 0; i < 10000; i++) {
count();
}
}
}
public class Sychronise {
public static void main(String[] args) {
Thread a1 = new Thread(new hehe());
Thread a2 = new Thread(new hehe());
a1.start();
a2.start();
try {
a1.join();
a2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(hehe.count);
}
}
The count should be 20000, but my output is still unstable.
Currently, your synchronized does nothing as it's synchronizing on each individual 'hehe' instance. To make it synchronize on the Class object (which owns the 'count' variable) make your count method static too:
public static synchronized void count(){
count++;
}
Or synchronize on an object:
public class hehe implements Runnable {
static int count= 0;
static Object lock = new Object();
public void count(){
synchronized(lock) {
count++;
}
}
public void run(){
for (int i=0;i<10000;i++){
count();
}
}
}
The issue here is that your count method is synchronized but there are 2 instances of the object Hehe, so each synchronization would be scoped to each instance, in this case I would suggest to use an AtomicInteger
First try with a static count method.
public static synchronized void count(){
count++;
}
public void run(){
for (int i=0;i<10000;i++){
Hehe.count();
}
}
I have two methods in two different classes, like this
public class ClassX implements Runnable {
public void methodAandB() {
for(int i=0;i<10;i++) {
System.out.println("This is A and B ");
}
}
#Override
public void run() {
methodAandB();
}
}
public class ClassY implements Runnable {
public void methodAorB() {
for(int i=0;i<10;i++) {
System.out.println("This is A or B");
}
}
#Override
public void run() {
methodAorB(a);
}
}
Thread t1 is calling methodAandB().
Thread t2 is calling methodAorB().
Can I switch between these two threads after each iteration of loop in methods?
I want to get output like this:
This is A and B
This is A or B
This is A and B
This is A or B
This is A and B
This is A or B
This is A and B
This is A or B
Best example of flip-flop between threads:
Given two int array (even and odd), 2 threads printing their numbers in natural order.
package com.rough;
public class ThreadsBehaviour {
static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
int a[] = {1,3,5,7,9};
int b[] = {2,4,6,8,10};
Thread odd = new Thread(new Looper(a, lock));
Thread even = new Thread(new Looper(b, lock));
odd.start();
even.start();
}
}
class Looper implements Runnable
{
int a[];
Object lock;
public Looper(int a[], Object lock)
{
this.a = a;
this.lock = lock;
}
#Override
public void run() {
for(int i = 0; i < a.length; i++)
{
synchronized(lock)
{
System.out.print(a[i]);
try
{
lock.notify();
if(i == (a.length - 1))
{
break;
}
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
You can achieve this simply by using the shared variables. I have implemented and verified the problem. code is below
class X
public class ClassX implements Runnable {
public void methodAandB() {
for(int i=0;i<10;i++) {
while(GlobalClass.isClassXdone)
{}
System.out.println("This is A and B ");
GlobalClass.isClassXdone = true;
GlobalClass.isClassYdone = false;
}}
#Override
public void run() {
methodAandB(); } }
ClassY
public class ClassY implements Runnable {
public void methodAorB() {
for(int i=0;i<10;i++) {
while(GlobalClass.isClassYdone)
{}
System.out.println("This is A or B ");
GlobalClass.isClassYdone = true;
GlobalClass.isClassXdone = false;}}
#Override
public void run() {
methodAorB();}}
Definition of the shared variable
public class GlobalClass {
public static boolean isClassXdone = false ;
public static boolean isClassYdone = false ;
}
You can just start your thread using t1.start and t2.start to get the desired output
Thread t1 = new Thread(new ClassX());
Thread t2 = new Thread(new ClassY());
t1.start();
t2.start();
This is probably more than needed to solve the problem, but, as it seems to be an introduction to concurrent programming exercise, it should be along the lines of what you'll encounter.
You should probably have a shared object that both your threads know, so that they may synchronize through it. Like so:
public class MyMutex {
private int whoGoes;
private int howMany;
public MyMutex(int first, int max) {
whoGoes = first;
howMany = max;
}
public synchronized int getWhoGoes() { return whoGoes; }
public synchronized void switchTurns() {
whoGoes = (whoGoes + 1) % howMany;
notifyAll();
}
public synchronized void waitForMyTurn(int id) throws
InterruptedException {
while (whoGoes != id) { wait(); }
}
}
Now, your classes should receive their respective identifier, and this shared object.
public class ClassX implements Runnable {
private final int MY_ID;
private final MyMutex MUTEX;
public ClassX(int id, MyMutex mutex) {
MY_ID = id;
MUTEX = mutex;
}
public void methodAandB() {
for(int i = 0; i < 10; i++) {
try {
MUTEX.waitForMyTurn(MY_ID);
System.out.println("This is A and B ");
MUTEX.switchTurns();
} catch (InterruptedException ex) {
// Handle it...
}
}
}
#Override
public void run() { methodAandB(); }
}
ClassY should do the same. Wait for its turn, do its action, and then yield the turn to the other.
I know it's a little late to answer this. But it's yesterday only I have come across this question. So I guess it's never too late.. ;)
Solution, as #afsantos mentioned is having a shared object between the two threads and implementing mutual exclusion on the shared object. The shared object could be alternatively locked by the two threads. Two possible implementations are as follows. This is actually more like an extension of #afsantos solution. His work is hereby acknowledged.
Solution 1:
Blueprint of the object that will be shared is as follows.
public class MutEx {
public int whoGoes, howMany;
public MutEx(int whoGoes, int howMany) {
this.whoGoes = whoGoes;
this.howMany = howMany;
}
public synchronized void switchTurns(){
this.whoGoes = (this.whoGoes + 1) % 2;
notifyAll();
}
public synchronized void waitForTurn(int id) throws InterruptedException{
while(this.whoGoes != id)
wait();
}
}
Then, you could implement the ClassX as follows.
public class ClassX implements Runnable {
private final int MY_ID;
private final MutEx MUT_EX;
public ThreadOne(int MY_ID, MutEx MUT_EX) {
this.MY_ID = MY_ID;
this.MUT_EX = MUT_EX;
}
#Override
public void run(){
this.doTheWork();
}
public void doTheWork(){
for(int i = 0; i < 10; i++){
try {
MUT_EX.waitForMyTurn(MY_ID);
System.out.println("This is A and B");
MUT_EX.switchTurns();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
ClassY also will be the same, with whatever the differences you need to be there. Then, in the invocation (i.e. in the main method),
public static void main(String[] args) {
MutEx mutEx = new MutEx(0, 2);
Thread t1 = new Thread(new ClassX(0, mutEx);
Thread t2 = new Thread(new ClassY(1, mutEx));
t1.start();
t2.start();
}
Voila! You have two threads, alternating between each as you need.
Solution 2: Alternatively, you could implement the ClassX & ClassY as follows.
public class ClassX extends Thread{
Here, you are subclassing the java.lang.Thread to implement your requirement. For this to be invoked, change the main method as follows.
public static void main(String[] args) {
MutEx mutEx = new MutEx(0, 2);
ClassX t1 = new ClassX(0, mutEx);
ClassY t2 = new ClassY(1, mutEx);
t1.start();
t2.start();
}
Run this, and you have the same result.
If you don't need to use Thread try this code:
for (int i = 0; i < 20; i++) {
if (i % 2 == 0) {
methodAandB();
} else {
methodAorB();
}
}
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());
}