Synchronized block vs. synchronized method qualifier in Java - java

The following code
public class Coordination {
private volatile int counter = 0;
public static void main(String ... args) throws Exception {
new Coordination().volatileWithCoordination();
}
public synchronized void inc() {
counter++;
}
public void volatileWithCoordination() throws Exception {
Thread th1 = new Thread(new Runnable() {
#Override
public void run() {
for(int k = 0; k < 10_000_000; k++) {
synchronized(this) {
//inc();
counter++;
}
}
}});
Thread th2 = new Thread(new Runnable() {
#Override
public void run() {
for(int k = 0; k < 10_000_000; k++) {
//synchronized(this) {
inc();
//counter++;
//}
}
}});
th1.start();
th2.start();
th1.join();
th2.join();
System.out.println("counter: "+counter);
}
}
exhibits incorrect and non-deterministic result of counter: 18025867 whereas switching to:
inc();
//counter++;
in the Runnable of the first thread (th1) gives the expected output:
counter: 20000000
What's causing this lost update behavior and why would a synchronized method in this case behave differently to a synchronized(this) block?
Thank you in advance.

Your threads are synchronizing on different objects. Your th2 thread calls the synchronized inc() method, which synchronizes on an instance of the Coordination class; but when your th1 thread does synchronized(this), the this keyword refers to an instance of the anonymous inner Runnable class, not to the Coordination class.

Both threads need to acquire a monitor on the same object, the following change (on either of the 2 threads or both) fixes the situation:
synchronized(Coordination.this) {
inc();
//counter++;
}

Related

Synchronized, join, and thread safety

I have read through other examples, but do not understand why this code with the commented out t.join() does not always have the end value 5000 for count, but when the code is commented in, count always is 5000 at the end. But why? I thought that the static lock object can only be owned by one thread at a time and when it is owned that the other threads have to wait until it is released. So I do not understand why join() is necessary and what exactly is happening.
import java.util.ArrayList;
public class MyClass implements Runnable {
private static int count = 0;
private static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
ArrayList<Thread> threads = new ArrayList<>();
for (int i = 1; i <= 5000; i++)
threads.add(new Thread(new MyClass()));
for (Thread t : threads)
t.start();
// for (Thread t : threads)
// t.join();
System.out.println("Total count = " + MyClass.getCount());
}
public void run() {
synchronized (lock) {
count++;
}
}
public static int getCount() {
return count;
}
}

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.

how to implement wait,notify with threadexecutor in java

how to implement wait,notify with threadexecutor in java,Suppose I have two objeccts of threadExecutor and I want to perform wait,notify on that objecct can we implement that.
Here is an Example of using wait notify with ThreadExecutor in Java :
public class ExecutorServiceTest {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
ThreadB threadB = new ThreadB();
ThreadA threadA = new ThreadA(threadB);
executor.execute(threadA);
executor.execute(threadB);
executor.shutdown();
while (!executor.isTerminated());
System.out.println("Finished all threads");
}
static class ThreadA extends Thread {
private final ThreadB waitThread;
public ThreadA(ThreadB waitThread) {
this.waitThread = waitThread;
}
#Override
public void run() {
synchronized (waitThread) {
try {
waitThread.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B Count Total : " + waitThread.getCount());
for (int i = waitThread.getCount(); i < 200; i++) {
System.out.println("A Counting " + i);
}
}
}
}
static class ThreadB extends Thread {
private int count = 0;
#Override
public void run() {
synchronized (this) {
while (count < 100) {
System.out.println("B Counting " + count);
count++;
}
notify();
}
}
public int getCount() {
return count;
}
}
}
synchronized
keyword is used for exclusive accessing.
To make a method synchronized, simply add the synchronized keyword to its declaration. Then no two invocations of synchronized methods on the same object can interleave with each other.
synchronized statements must specify the object that provides the intrinsic lock:
wait()
tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify( ).
notify()
wakes up the first thread that called wait() on the same object.

Mutithreading Synchronization

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.

The output of the counter to this multi-threaded code

I came across a Java problem about multi-threaded programming (please see the code below). Based on this question and answer on StackOverflow, I think I understand why there could be a deadlock. But what I don't understand was if the program works correctly (i.e. there is no deadlock), what would be the value of foo printed? I thought it would be 20 (thread1 counting up to 10 and thread2 counting up to 10 more). Could someone help me explain how this might (preferably in a simple way because I'm still new to thread programming)? Thank you.
public class ThreadTest{
private static class ThreadOne extends Thread{
private ThreadTwo threadTwo;
public int foo = 0;
public void setThreadTwo(ThreadTwo th){
threadTwo = th;
}
public void run(){
try{
for(int i=0;i<10;i++) foo += i;
synchronized(this){this.notify();};
synchronized(threadTwo){threadTwo.wait();};
System.out.print("Foo: " + threadTwo.foo);
}catch(InterruptedException e){ e.printStackTrace();}
}
}
private static class ThreadTwo extends Thread{
private final ThreadOne threadOne;
public int foo = 0;
public ThreadTwo(ThreadOne th){
threadOne = th;
}
public void Run(){
try{
synchronized(threadOne){threadOne.wait();}
foo = threadOne.foo;
for(int i=0;i<10;i++) foo += i;
synchronized(this){this.notify();};
}
catch(InterruptedException e){e.printStackTrace();}
}
}
public static void main(){
ThreadOne th1 = new ThreadOne();
ThreadTwo th2 = new ThreadTwo(th1);
th1.setThreadTwo(th2);
th1.start(); th2.start();
th1.join(); th2.join();
}
}
According to your code and without deadlocks foo value will be 90 (if i didn't miscalculate). Because instead of foo += 1 you did foo += i.
EDIT: Okay, step by step.
foo = 0
th1 and th2 starts. th2 waits for notify. th1 increments foo up to 45
th1 notifies and starts to wait th2. th2 is notified and starts to increment foo from 45 to 90
th2 notifies th1. th1 is notified, and it prints th2.foo, which is 90
EDIT 2: Correct way to count from 0 to 90 from 2 threads without concurrent modification is something like this
public class ThreadTest {
private static int counter = 0;
private static class Thread1 extends Thread {
final Object lock;
public Thread1(Object lock) {
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
for (int i = 0; i < 10; i++)
counter += i;
}
}
}
private static class Thread2 extends Thread {
final Object lock;
public Thread2(Object lock) {
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
for (int i = 0; i < 10; i++)
counter += i;
}
}
}
public static void main(String[] args) {
final Object lock = new Object();
final Thread th1 = new Thread1(lock);
final Thread th2 = new Thread2(lock);
th1.start();
th2.start();
try {
th1.join();
th2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Counter: " + counter);
}
}
But if you are forced to use wait and notify, than it's a bit more complicated. Use object of this class as common lock instead of Object
class Locker {
private boolean isLocked = false;
public synchronized void lock() throws InterruptedException {
while (isLocked) wait();
isLocked = true;
}
public synchronized void unlock() {
isLocked = false;
notify();
}
}
And in run method us it like this:
#Override
public void run() {
try {
locker.lock();
for (int i = 0; i < 10; i++)
counter += i;
locker.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Categories