Concurrency and Java Synchronization - java

Consider the following code:
public class MyObject{
synchronized void f() {
System.out.print("a ");
System.out.print("b ");
}
synchronized void g() {
System.out.print("z ");
System.out.print("x ");
}
void h() {
System.out.print("1 ");
System.out.print("2 ");
}
}
Thread 1 class
public class Thread1 implements Runnable {
MyObect myObject;
Thread1(MyObject t){
MyObject = t;
}
public void run() {
myObject.f();
}
}
Thread 2 class
public class Thread2 implements Runnable {
MyObect myObject;
Thread2(MyObject t) {
myObject = t;
}
public void run() {
myObject.g();
myObject.g();
}
}
Main method:
public static void main(String[] args) {
MyObject myObj = new MyObject();
Thread1 t1 = new Thread(new Thread1(myObj));
Thread1 t2 = new Thread(new Thread1(myObj));
t1.start();
t2.start();
}
When you run the main class, would all the possible outputs be
a b z x z x
z x z x a b
Or can Thread2 sleep in the middle which would result in something like
z x a b z x

Yes, it can sleep in the middle so all three are possible because it releases the lock after each call to g. Otherwise those methods are synchronized and guaranteed to run in their entirely.

Yes, it is possible to get something like zxabzx because you release the lock and require it in Thread 2

Remember that a Thread can always yield the processor (CPU/GPU) to another thread in the middle of its execution which is something very common when the thread executes for a long period of time ("long" meaning a couple of milliseconds)

can Thread2 sleep in the middle ?
Yes, it can, Thread 2 will have to release lock on MyObect as soon as execution of first g() completes.
So, It can allow other thread to take lock on MyObect before proceeding with the next g()

Related

How to check whether sleep() method in Java holds lock or not?

class MyThread extends Thread{
public void run(){
print();
}
synchronized public void print() {
// for(int i = 0; i< )
System.out.println("Thread : " + Thread.currentThread().getName());
try{
Thread.sleep(5000);}
catch(InterruptedException e ){
}
}
}
public class MyClass {
public static void main(String args[]) throws InterruptedException {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.setName("A");
t2.setName("B");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("EOM");
}
}
Output of the Program -
ThreadA
ThreadB
Immediately prints both line
After 5 seconds
EOM
According to my understanding, one of the thread should go in print() and acquire lock and only releases it after 5 seconds but here both the threads executed immediately and then "EOM" got printed after 5 seconds.
The synchronized is in an instance method, and each instance doesn't interfere with each other.
If the method were static then it would be shared between the instances.
You wrote:
synchronized public void print() {
...
}
That's just a short-cut way of writing:
public void print() {
synchronized(this) {
...
}
}
Each of your two threads is operating on a different instance of your MyClass class, therefore, each of your two threads is synchronizing on a different object (different this reference).
When you use synchronized(o) blocks, that only prevents two different threads from synchronizing on the same object o at the same time.

why without calling the notify wait is releasing the lock

Please see the below code, where the notifyAll is commented. Still the main thread is printing the total? How is it possible?
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}}
class ThreadB extends Thread{
int total;
#Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
// notify();
}
}
}
What you see is the result of something documented in the javadoc of Thread.join():
As a thread terminates the this.notifyAll method is invoked.
Note that it goes on with
It is recommended that applications not use wait, notify, or notifyAll on Thread instances
Also note that a thread blocked on wait() can go out of its waiting state without any notification, due to spurious wakeups. And the javadoc of wait() clearly explains that wait() should always be called inside a loop.
Also note: The Java API doc for Object.wait() says, "...interrupts and spurious wakeups are possible, and this method should always be used in a loop."
That is generally true in other APIs and other languages as well. A method/function should never assume that the condition it was waiting for is true just because a wait() operation on a condition variable returned. There should always be a loop. In pseudo-code:
lock mutex
while (! ok_to_do_whatever()) {
wait on condition_variable
}
do_whatever()
unlock mutex
Try this and the waiting thread will wait forever...
public class ThreadA {
public static Object lock = new Object();
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
synchronized(lock){
try{
System.out.println("Waiting for b to complete...");
lock.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread
{
int total;
#Override
public void run(){
synchronized(ThreadA.lock){
for(int i=0; i<100 ; i++){
total += i;
}
// notify();
}
}
}

Implementing deadlock condition

I am trying to implementing deadlock condition but somehow I am not able to get it working. Both the threads Thread1 and Thread2 are entering in the run function but only one of them enters in Sub/Sum depending on who entered run first. Example : if Thread2 entered run first the it will call sub() and Thread1 never calls sum(). I have also added sleep time so that Thread2 sleeps before calling sum() and Thread1 gets enough time to enter Sum() but Thread1 never enters.
public class ExploringThreads {
public static void main(String[] args) {
// TODO Auto-generated method stub
threadexample a1 = new threadexample();
Thread t1 = new Thread(a1, "Thread1");
Thread t2 = new Thread(a1,"Thread2");
t1.start();
t2.start();
}
}
class threadexample implements Runnable{
public int a = 10;
public void run(){
if(Thread.currentThread().getName().equals("Thread1"))
sum();
else if(Thread.currentThread().getName().equals("Thread2"))
sub();
}
public synchronized void sum()
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"In Sum");
sub();
}
public synchronized void sub()
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"In Sub");
sum();
}
}
If you really want to create an artificial dead lock, try this:
Thread1 and Thread2 are two threads that want to access the same file.
Thread1 starts, asks for a lock on File1.docx and sleeps for 2 minutes.
Thread2 starts, and makes an exclusive lock on File2.docx and now wants to access File1.docx.
Thread1 wakes up and now wants to access File2.docx which is held by Thread2
Now, this is a circular wait condition
Simple ? =)
This is not how you get a deadlock. Actually this code seems pretty safe :-) Only one thread enters sum/sub at a time because you are using synchronized which synchronizes on "this". There is only one "this" so both threads try to acquire the same lock.
Deadlock occurs, for instance, when Thread1 has one lock, Thread2 has second lock and then Thread1 would like to acquire Thread2's lock while still holding it's lock and Thread2 would like to acquire Thread1's lock while still holding it's lock.
What you could do is:
a) add 2 objects for locking in "threadexample" class (btw classes by convention should start with uppercase):
private final Object sumLock = new Object();
private final Object subLock = new Object();
b) drop the "synchronized" keyword in both sum/sub methods and instead use the synchronized() {} block in each of them. Sum would be synchronized(sumLock) { /* sum's body goes here / } and sub would be synchronized(subLock) { / sub's body goes here */}.
In this case Thread1 would go into sum(), acquire the sumLock and wait. Thread2 would go into sub(), acquire the subLock() and wait. Thread1 would wake up, go into sub() and try to acquire subLock but it's being held by Thread2 so it wait's until Thread2 releases it. In that time Thread2 wakes up, goes into sum() and tries to acquire sumLock which is held by Thread1 so Thread2 waits for Thread1 to release it.
Neither thread will go forward as each one of them is waiting for the other - you have a deadlock.
#Edit: yes you have only 1 instance of "threadexample" and both Thread1 and Thread2 are fighting for the lock but when one of them acquires the lock it will release it after executing sum/sub or sub/sum. For instance let's say Thread1 is first and starts executing sum(). It has the lock. In that case Thread2 will not go into sub() as it is protected by the same lock as Thread1. Thread1 will do sum(), then sub() and then it will release the lock --> Thread2 will go into sub() etc.
This is a working example of 'Deadlock in Action'. Basically what you need to do (and how that usually happens in real world) is that object are locked in opposite order: a first, b second in one thread and b first, a second in another:
package stackoverflow;
public class Deadlock {
final static String a = new String("A");
final static String b = new String("B");
public static void main(String[] args) {
final Thread abLock = new Thread() {
#Override
public void run() {
lock(a, b);
}
};
final Thread baLock = new Thread() {
#Override
public void run() {
lock(b, a);
}
};
abLock.start();
baLock.start();
}
static void lock(String first, String second) {
synchronized (first) {
System.out.println(first);
sleep();
synchronized (second) {
System.out.println(second);
}
}
}
static void sleep() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

Thread Synchronization Behaviour

class Untitled {
public static void main(String[] args) {
MyRunnable r1 = new MyRunnable();
Thread t1 = new Thread(r1,"Thread 1:");
Thread t2 = new Thread(r1,"Thread 2:");
t1.start();
t2.start();
}
}
class MyRunnable implements Runnable
{
String s1 = "Hello World";
String s2 = "Hello New World";
public void run()
{
synchronized(s1)
{
for(int i =0;i<3;++i)
System.out.println(Thread.currentThread().getName()+s1);
}
synchronized(s2)
{
for(int i = 0;i<3;++i)
System.out.println(Thread.currentThread().getName()+s2);
}
}
}
OUTPUT:
Thread 1:Hello World
Thread 1:Hello World
Thread 1:Hello World
Thread 1:Hello New World
Thread 2:Hello World
Thread 1:Hello New World
Thread 2:Hello World
Thread 1:Hello New World
Thread 2:Hello World
Thread 2:Hello New World
Thread 2:Hello New World
Thread 2:Hello New World
Why can't Thread2 execute the second synchronized block in the run() method when Thread1 is executing the first synchronized block even though lock objects are different.Does Thread2's execution wait at the first synchronized block till Thread1 leaves that block??
If so how to make both synchronized blocks run concurrently??
Does Thread2's execution wait at the first synchronized block till Thread1 leaves that block??
Yes that's the idea - thread2 executes the blocks one after the other. If it is blocked and can't enter the first one, it will wait there until the s1 lock becomes available.
If so how to make both synchronized blocks run concurrently??
You would need to split them in two different runnables and use one thread for each.
Because within the run method statements are executed in sequentially not parallely.
So who ever Thread 1 or Thread 2 acquire the lock of s1 other will wait untill it is released.
The two blocks are one after the other, which means that Thread 2 has to go though block 1 before going through block 2
Why can't Thread2 execute the second synchronized block in the run()
method when Thread1 is executing the first synchronized block
Code is executed line by line, The execution doesnt jump to next block and Thread 2 waits for Thread 1 to leave the 1st Synchronized block.
Does Thread2's execution wait at the first synchronized block till
Thread1 leaves that block
Yes.
If so how to make both synchronized blocks run concurrently??
So keep them In seperate Runnable Instances. and Not one after the other in a Sequence.
It is simply the compiler execute the code i.e. compiler execute code in sequence the way they are written. thread 2 cannot skip first block of code. it will first execute first block then others.
Here's an example of getting them both to run concurrently. Note that not only have I put each loop in a separate thread but I have reduced the scope of the synchronization to just the print.
public class Test {
static class MyRunnable implements Runnable {
final String s1 = " Hello World - ";
final String s2 = " Hello New World - ";
static final int n = 10;
#Override
public void run() {
// Two loops in two threads.
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < n; ++i) {
// Scope reduced.
synchronized (s1) {
System.out.println(Thread.currentThread().getName() + s1 + i);
}
}
}
}, Thread.currentThread().getName() + "(a)").start();
// Two loops in two threads.
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < n; ++i) {
// Scope reduced.
synchronized (s2) {
System.out.println(Thread.currentThread().getName() + s2 + i);
}
}
}
}, Thread.currentThread().getName() + "(b)").start();
}
}
public void test() {
MyRunnable r1 = new MyRunnable();
Thread t1 = new Thread(r1, "Thread 1:");
Thread t2 = new Thread(r1, "Thread 2:");
t1.start();
t2.start();
}
public static void main(String args[]) {
new Test().test();
}
}
class ThreadExample {
public static void main(String[] args) {
MyRunnable15756 r1 = new MyRunnable15756();
Thread t1 = new Thread(r1,"Thread 1:");
Thread t2 = new Thread(r1,"Thread 2:");
t1.start();
t2.start();
}
}
class MyRunnable15756 implements Runnable
{
String s1 = "Hello World";
String s2 = "Hello New World";
Runnable runnable1 = new Runnable(){
#Override
public void run() {
synchronized(s1)
{
for(int i =0;i<30;++i)
System.out.println(Thread.currentThread().getName()+s1);
}
}
};
Runnable runnable2 = new Runnable(){
#Override
public void run() {
synchronized(s2)
{
for(int i = 0;i<30;++i)
System.out.println(Thread.currentThread().getName()+s2);
}
}
};
public void run()
{
new Thread(runnable1).start();
new Thread(runnable2).start();
}
}

spawnining more threads

I have developed a program in which the thread A waits for Thread B to complete it task and when thread B finishes its task it makes notfiy() to thread A to continue onwards..below is the code..
class ThreadA {
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
synchronized(b) {
try {
System.out.println("Waiting for b to complete...");
b.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.totals);
}
}
}
class ThreadB extends Thread {
public int totals;
public void run() {
synchronized(this) { //instance level lock
for(int i=0;i<100;i++) {
totals += i;
}
notify();
}
}
}
Now I want lets say 3 more thread are waiting for thread b , so please advise me how to spawn 3 more threads , just like thread A is waiting , please advise.
Use the ExecutorService it has a methode invokeAll(). You can submit all your ThreadB and hold a List of Future's.
Your current code actually contain possible deadlock since you start() the threadB first and it is calling the notify() in its run(). This notify() is possible to be called before the wait() in the main. If this happens, you threadB will be waiting forever.
To start more ThreadB, you just need to create more instances.
ThreadB threadBs = new ThreadB[3];
for (ThreadB b : threadBs) {
b = new ThreadB();
b.start();
}
However, I will suggest implementing the Runnable interface instead of just extending the Thread class.

Categories