Mutithreading Synchronization - java

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 ?

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.

You are creating two objects here.
synchronized(this) block will synchronize access to the same object if multiple threads try to access it.

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.

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);
}
}
}
}

// 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.

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.

Related

Synchronized method does not work but synchronized block does, why?

public class driver{
public static void main(String[] args) {
PrintNum firstObjectForThread = new PrintNum(0); // the argument is not used, ignore it
firstObjectForThread.startNewThread();
PrintNum secondObjectForThread = new PrintNum(0);
secondObjectForThread.startNewThread();
}
This is the class that the driver calls:
public class ClassName implements Runnable{
int variableForUpdate;
private Thread t;
private static ArrayList<Integer> intArray;
public ClassName(int variableForUpdate) {
super();
this.intArray = new ArrayList<Integer>();
this.variableForUpdate = variableForUpdate;
for (int i = 0; i < 30 ; i++) {
this.intArray.add(i);
}
}
#Override
public void run() {
runThisWhenThreadStarts();
}
private synchronized void runThisWhenThreadStarts() {
System.out.println("Started");
for (int i = 0; i < 30; i++) {
System.out.println(intArray.get(i));
}
}
public void startNewThread() {
t = new Thread(this);
t.start();
}
}
If I use block synchronization the following, the output is synchronized:
private void runThisWhenThreadStarts() {
synchronized (ClassName.class) {
System.out.println("Started");
for (int i = 0; i < 30; i++) {
System.out.println(intArray.get(i));
}
}
}
I have been troubleshooting this for many hours and cannot figure out... Can anyone shed some light please?
I also notice if I use the same object to call startNewThread(), the synchronization will work. But I don't understand why.
PrintNum firstObjectForThread = new PrintNum(0); // the argument is not used, ignore it
firstObjectForThread.startNewThread();
firstObjectForThread.startNewThread();
I want to use two different object from the same class instead of one object calling the method twice (the workaround above).
I am able to use the synchronized methods in another program, with 2 different instances (get and put) :
public class Hello extends Thread {
int x;
Coffee x1;
int threadno;
Hello(int x, Coffee x1) {
this.x = x;
threadno = x;
this.x1 = x1;
}
public void run() {
switch (x) {
case 0:
System.out.println("Start thread " + threadno + " Get");
break;
case 1:
System.out.println("Start thread " + threadno + " Put");
break;
}
ops();
System.out.println("Stopping thread " + threadno);
}
public void ops() {
x1.get();
}
public static void main(String[] args) {
Coffee c1 = new Coffee();
Hello get = new Hello(0, c1);
Hello put = new Hello(0, c1);
get.start();
put.start();
}
}
Hello class will call coffee class:
class Coffee {
boolean available = false; // indicating there nothing to get.
// waiting on each other.
int contents = 55;
public synchronized int get() {
System.out.println("Entering Get method " + contents);
for (int i = 0; i < 30; i++) {
System.out.println(i);
}
return contents;
}
}
In the first example, the method acquires the lock on the object instance that the method is called on. The block doesnt do that, instead it acquires the lock on the class.
Taking the lock on the instance has no effect on the other thread, it is a different object. Both threads are acquiring their own lock, which is useless. Neither thread is prevented from doing anything.
Taking the lock on the class means both threads are trying to acquire the same lock. For locking to work the same lock has to be used by both threads.
In the second example the Coffee object is shared by both threads, and both threads are trying to acquire the same lock on the Coffee object. That means the second thread to get to the lock has to block until the lock is released by the first thread, locking successfully keeps the thread out until the first thread is done.
To understand synchronized, keep track of what locks are being acquired.

Unable to understand sync

Hey I am trying to make 10 threads in a synchronized manner and I came up with the code below however I am not able to understand a part of it as mentioned below. I am still really new to java, I tried looking up synchronized threading from
Here but still I am clueless.
class question3 {
public static void main(String arg[]) throws Exception {
for (int i = 0; i < 11; i++) {
data di = new data();
System.out.println(di.count);
}
}
}
class item {
static int count = 0;
}
class data extends item implements Runnable {
item d = this;
Thread t;
data() {
t = new Thread(this);
t.start();
}
public void run() {
d = syn.increment(d);
}
}
class syn {
synchronized static item increment(item i) {
i.count++;
return (i);
}
}
I am not sure what this part of code does?
public void run() {
d = syn.increment(d);
}
}
class syn {
synchronized static item increment(item i) {
i.count++;
return (i);
}
}
the run function is used when starting the thread, this is a must function you need to override when implement Runnable. When calling Thread.start(), the run function will be called.
The class syn contains a synchronized method, it is simply mean that only one thread can access it each time, thus make the incerment function thread safe.
object d has a static variable count meaning all instances of item class (and data ) share the same count, so all threads increment the same variable
the line d = syn.increment(d); is basically count++ but in a thread safe way

Impact of one synchronized from another synchronized method in multi-thread environment?

I am working with the synchronization threads where I have three synchronized method and each method will access by individual thread (Total 3 threads in current program )
In our program we are calling one syn method is calling another sync method, below is sample code which is inspired from real application :
public class ThreadTest {
public static synchronized void suncMessage() {
System.out.print("1");
}
public static synchronized void suncMessage2() {
suncMessage();
System.out.print("2");
}
public static synchronized void suncMessage3(String s) {
System.out.print("3m" + s);
}
public static void main(String... at) throws InterruptedException {
Thread t1 = new Thread() {
public void run() {
for (int i = 0; i <= 2; i++) {
suncMessage();
}
}
};
Thread t2 = new Thread() {
public void run() {
for (int i = 0; i <= 2; i++) {
suncMessage2();
}
}
};
Thread t3 = new Thread() {
public void run() {
for (int i = 0; i <= 2; i++) {
suncMessage3("3");
}
}
};
t1.start();
t2.start();
t3.start();
}
}
So my question is, what is impact of calling one synch. method from another synch.?? Is it good practices and how it will impact the complexity of program?
Nice question, but you have to try hard when you are working on this type of scenarios and the performance may effect. Because synchronization is approx 50 time slower than normal method.

synchronized in thread concepts of java

When I try to execute the piece of code, I am getting output like 12221121212121221212. When I declare the method as synchronized, it should not allow the other thread to take over the control
package com.test;
public class TestProject extends Thread {
public void run() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.print(getName());
}
}
}
public static void main(String[] args) throws InterruptedException {
TestProject myProject = new TestProject();
TestProject myProject1 = new TestProject();
myProject.setName("1");
myProject1.setName("2");
myProject.start();
myProacject1.start();
}
}
So, how do I alter the code to get a output of 11111111112222222222 or 22222222221111111111 in sequential format?
You are synchronizing on this, i.e. on the TestProject object. Since you have two separate objects, you have two separate locks. Consequently, both threads can enter the synchronized section irrespective of what the other thread is doing.
To synchronize across instances of TestProject you need a static lock:
public class TestProject extends Thread {
private static final Object lock = new Object();
public void run() {
synchronized (lock) {
...
Java uses biased locking by default. This means a lock will favour the last thread to access a lock. If you consider that one thread can start, run and finish before the other even starts I would expect you get one thread running to completion before the other starts most of the time.
I have just noticed you lock outside the loop. This will guarantee you also run one thread to completion before the other starts.
This is how you can enforce fair alternation of threads.
public class TestProject implements Runnable {
private final Lock lock;
public TestProject(Lock lock) {
this.lock = lock;
}
public void run() {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
System.out.print(Thread.currentThread().getName());
} finally {
lock.unlock();
}
}
}
public static void main(String... ignored) {
Lock lock = new ReentrantLock(true);
new Thread(new TestProject(lock), "1").start();
new Thread(new TestProject(lock), "2").start();
}
}
can print
12121212121212121212
Note: if you make the lock non-fair you can get (change the true to false)
11111111112222222222
Note: if you want fair alternation between two tasks, it much simpler to use one thread and a loop.
public static void main(String... ignored) {
for (int i = 0; i < 10; i++) {
// task 1
System.out.print("1");
// task 2
System.out.print("2");
}
}
you can also use join method on myProject1 so that it waits for the other thread to finish
these are the following method that can be used to achieve synchronization among the thread
1). use a static global lock and pass that object variable as argument to the synchronized block
2). use join()
3). create a instance for the Object class and pass that as an argument to the synchronized block like this Object myObject = TestProject.class now pass myObject to the synchronized block
using either of the above ways we can achieve synchronization

Why does this thread data race?

I am new to threads and learning. Why does this data race? I know how to do it using the Synchronized(){} method but not with the modifier.
public class SyncMethodDataRace extends Thread {
private static int common = 0;
public synchronized void run(){
int local = common;
local++;
common = local;
}
public static void main(String[] args) throws InterruptedException {
SyncMethodDataRace[] allThreads = new SyncMethodDataRace[20000];
for(int i = 0; i < allThreads.length; i++){
allThreads[i] = new SyncMethodDataRace();
}
for(SyncMethodDataRace d: allThreads){
d.start();
}
for(SyncMethodDataRace d: allThreads){
d.join();
}
System.out.println(common);
}
}
By making run method synchronized you did not achieve the desired synchronization. A synchronized method locks on the current instance of the class. In your example, no other thread is calling the run method of another thread, so there is no blocking.
In your case you probably need a static object that is shared among all instances to synchronize on, ie:
private static Object syncObject = new Object();
public void run() {
synchronized (syncObject) {
//....
}
}

Categories