Java provides a number of features that help you avoid common concurrency problems. For example, synchronization keyword makes it possible to declare volatile variables that never cache their values and are guaranteed to be visible. This makes them useful for synchronizing single variables, but not for classes or methods. If you declare a variable as volatile, it will be read from main memory when it is used in other threads.

During a thread’s execution, the object lock on its block will be acquired, and it will be released when the thread exits. This is the key to performance in Java code. To understand the performance cost of using a synchronized block, let’s start with a definition of a synchronized block.

Synchronized block

Java synchronization works by using a monitor lock, also known as an intrinsic lock. The monitor lock is bound to the object. This means that only one thread can execute synchronized blocks of the same object. This applies to both static and instance methods.

A synchronizing block is a special kind of method that can be used by two or more threads at the same time. For example, you can use a synchronizing block to execute a method on a class object while another thread executes it in another thread. This type of method is also called partial synchronization.

Synchronizing blocks are not synchronized by default. They can have small performance overhead. You can use volatile variables to avoid this performance overhead.

Synchronized block in a static method in Java adds an extra layer of indirection to the process of getting and storing data. It also makes it slower than the same method that uses a non-synchronized method. It is better to avoid synchronized methods as much as possible. For example.

Synchronized blocks are only efficient for blocking threads that share the same Java virtual machine (VM). When the same Java application runs on multiple Java VMs, other threads can enter and exit the same synchronized block at the same time. In such a case, you need to use some other synchronization mechanism to ensure that multiple threads aren’t using the same object.

Enum avoiding deadlock during instantiation

A deadlock is a situation in which two threads repeatedly block each other without completing any work. This can be prevented by implementing code to break hold and wait. However, this approach is not scalable, since most systems perform work in between semaphore acquisitions.

For example, if a thread calls the asynchronous task, it will block until it is able to return the result. In this case, the programmer should ensure that the object’s lifetime is longer than the duration of the thread. This is possible with the help of enums.

package com.theprogramguide;

class ThreadDemo2 extends Thread{
    SynDemo t;
    ThreadDemo2(SynDemo t){
        this.t=t;
    }
    public void run(){
        try {
            t.test(20);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
package com.theprogramguide;

class ThreadDemo1 extends Thread{
    SynDemo t;
    ThreadDemo1(SynDemo t){
        this.t=t;
    }
    public void run(){
        try {
            t.test(2);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
package com.theprogramguide;

public class SynTest {
    public static void main(String args[]){
        SynDemo obj = new SynDemo();
        ThreadDemo1 a=new ThreadDemo1(obj);
        ThreadDemo2 b=new ThreadDemo2(obj);
        a.start();
        b.start();
    }
}
package com.theprogramguide;

public class SynDemo {
    // //synchronized method
    synchronized void test(int j) throws InterruptedException {
        for(int i=1;i<=3;i++){
            System.out.println(j*i);
                Thread.sleep(1000);
    }
    }
}