Core Java Questions

to make variable Thread Safe
volatile – the changes made in the variable are immediately reflected in case of volatile
static – Note that volatile should not be confused with the static modifier. static variables are class members that are shared among all objects. There is only one copy of them in the main memory.

volatile vs synchronized

Before we move on let’s take a look at two important features of locks and synchronization.

Mutual Exclusion It means that only one thread or process can execute a block of code (critical section) at a time.
Visibility It means that changes made by one thread to shared data are visible to other threads.

Java’s synchronized keyword guarantees both mutual exclusion and visibility. If we make the blocks of threads that modifies the value of shared variable synchronized only one thread can enter the block and changes made by it will be reflected in the main memory. All other thread trying to
enter the block at the same time will be blocked and put to sleep.

In some cases, we may only desire visibility and not atomicity. The use of synchronized in such a situation is overkill and may cause scalability problems. Here volatile comes to the rescue.
Volatile variables have the visibility features of synchronized but not the atomicity features

Class level locking vs Object level locking

Synchronization : Is a modifier which is used for method and block only. With the help of synchronized modifier we can restrict a shared resource to be accessed only by one thread. When two or more threads need access to shared resources, there is some loss of data i.e. data inconsistency. The process by which we can achieve data consistency between multiple threads it is called Synchronization.

Why do you need Synchronization?
Let us assume if you have two threads that are reading and writing to the same ‘resource’. Suppose there is a variable named as geek, and you want that at one time only one thread should access the variable(atomic way). But Without the synchronized keyword, your thread 1 may not see the changes thread 2 made to geek, or worse, it may only be half changed that cause the data inconsistency problem. This would not be what you logically expect. The tool needed to prevent these errors is synchronization.

In synchronization, there are two types of locks on threads:

  1. Object level lock : Every object in java has a unique lock. Whenever we are using synchronized keyword, then only lock concept will come in the picture. If a thread wants to execute synchronized method on the given object. First, it has to get lock of that object. Once thread got the lock then it is allowed to execute any synchronized method on that object. Once method execution completes automatically thread releases the lock. Acquiring and release lock internally is taken care by JVM and programmer is not responsible for these activities. Lets have a look on the below program to understand the object level lock:

Object level lock is mechanism when we want to synchronize a non-static method or non-static code block such that only one thread will be able to execute the code block on given instance of the class. This should always be done to make instance level data thread safe.

Object level locking can be done as below :

Various ways for object level locking
public class DemoClass
{
public synchronized void demoMethod(){}
}

or

public class DemoClass
{
public void demoMethod(){
synchronized (this)
{
//other thread safe code
}
}
}

or

public class DemoClass
{
private final Object lock = new Object();
public void demoMethod(){
synchronized (lock)
{
//other thread safe code
}
}
}

2. Class level lock : Every class in java has a unique lock which is nothing but class level lock. If a thread wants to execute a static synchronized method, then thread requires class level lock. Once a thread got the class level lock, then it is allowed to execute any static synchronized method of that class. Once method execution completes automatically thread releases the lock. Lets look on the below program for better understanding:

Class level locking should always be done to make static data thread safe. As we know that static keyword associate data of methods to class level, so use locking at static fields or methods to make it on class level.

Various ways for class level locking
public class DemoClass
{
//Method is static
public synchronized static void demoMethod(){

}

}

or

public class DemoClass
{
public void demoMethod()
{
//Acquire lock on .class reference
synchronized (DemoClass.class)
{
//other thread safe code
}
}
}

or

public class DemoClass
{
private final static Object lock = new Object();

public void demoMethod()
{
    //Lock object is static
    synchronized (lock)
    {
        //other thread safe code
    }
}

}

Java ClassLoaders

  • Load Classes in JVM Memory
  • Three builtin classloaders: 1. 1. bootstrap 2. extensions 3. system
  • can create custom classloaders

What is Deadlock? How to analyze and avoid deadlock situation?

Deadlock is a programming situation where two or more threads are blocked forever, this situation arises with at least two threads and two or more resources.

To analyze a deadlock, we need to look at the java thread dump of the application, we need to look out for the threads with state as BLOCKED and then the resources it’s waiting to lock, every resource has a unique ID using which we can find which thread is already holding the lock on the object.

Avoid Nested Locks, Lock Only What is Required and Avoid waiting indefinitely are common ways to avoid deadlock situation, read this post to learn how to analyze deadlock in java with a sample program.