Reputation: 335
Synchronization works well with the below code.
public class Main implements Runnable {
public static void main(String[] args) {
Main m = new Main();
for (int i = 0; i < 2; i++) {
Thread t = new Thread(m);
t.start();
}
}
@Override
public void run() {
synchronized(this) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
}
}
}
// Synchronization isn't working here.
public class Main implements Runnable {
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new Main());
t.start();
}
}
@Override
public void run() {
synchronized(this) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
}
}
}
This question was asked in an interview. I was a bit confused about this so I'm trying to understand why synchronization isn't working with the second code snippet. Can anybody explain me why synchronization won't work with the second code snippet ?
Upvotes: 2
Views: 116
Reputation: 27115
I would have answered that question with a question of my own:
What do you mean, it doesn't work?
The first example serializes the System.out.println()
calls and, for the reasons given in several of the other answers here, the second example doesn't serialize the calls, but so what?
System.out
is a java.io.PrintWriter
, and PrintWriter
is inherently thread-safe. Neither of the two examples needs synchronization at all.
Upvotes: 0
Reputation: 4035
You are creating two objects here.
synchronized(this)
block will synchronize access to the same object if multiple threads try to access it.
Upvotes: 2
Reputation: 1299
// Synchronization isn't working here.
public class Main implements Runnable {
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new Main());
t.start();
}
}
@Override
public void run() {
synchronized(this) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
}
}
}
In above example there are 3 threads and 3 Main objects, each thread is taking a lock on different Main object so synchronization will not work.For synchronization to work we should have all threads to take a lock on the single object. Here 3 threads are not taking the lock on a single object but 3 different objects. Each thread is taking a lock on each main object which is not shared among threads. In Thread t = new Thread(m); all threads take a lock on single Main(m) object.
Upvotes: 1
Reputation: 4692
Because synchronization is applied for if you are working on single object.
In first case you have single runnable object of Main i.e. m
In second case you have independent objects of Main.
for(int i=0;i<2;i++){
Thread t = new Thread(new Main()); // independent objects for each thread
t.start();
}
Explaination:
If you see the code you will find below line
synchronized (this) {
this
refers to the object itself. So lock is applied based on this object. So in case of multiple Main class object they work independently where as in single object synchronization is applied for that object only.
For more information refer : Intrinsic Locks and Synchronization
Code from the documentation
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) { // lock is acquired using lock1 object
c1++;
}
}
public void inc2() {
synchronized(lock2) { // lock is acquired using lock1 object
c2++;
}
}
}
In this example you can call both the methods inc1()
and inc2()
using single object at same time because lock is acquired on different objects. This will help you understand it better.
So in your case lock is acquired on this
(object itself). So whenever you have multiple object then it will work independently and when you have single object then it will work synchronously.
Upvotes: 6
Reputation: 10428
in Java syncronized(object)
is effectively using object
as an exclusive lock for the code block within syncronized
. It may be more obvious why the second version doesn't work if we make the lock explicit, and observe how many instances of the lock get created in each case:
public class Lock {
}
public class Main(Lock lock) implements Runnable {
public static void main(String[] args) {
correct()
incorrect()
}
public static void incorrect() {
for (int i = 0; i < 2; i++) {
//New lock created each iteration
Main m = new Main(new Lock())
Thread t = new Thread(m);
t.start();
}
}
public static void correct() {
//One lock used for all iterations
Main m = new Main(new Lock())
for (int i = 0; i < 2; i++) {
Thread t = new Thread(m);
t.start();
}
}
@Override
public void run() {
synchronized(lock) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
}
}
}
Upvotes: 1
Reputation: 5213
synchronized (this)
"this" is the current object instance. In the first example, instance of Main class is created before invoking the thread and same instance is used. Therefore synchronization works. But in the second example, in each iteration of the loop in main(), new instance of Main is created. synchronized(this) will not work because there are multiple instances of Main class.
Upvotes: 1