Java also provides more flexible locks which can be explicitly created, locked, and unlocked by the programmer. These implement Lock.

Reentrancy

Reentrant

Reentrant means that once a thread has obtained an object’s lock it can enter other synchronized blocks and methods on the same object. Java synchronized blocks and methods are reentrant.

Link to original

Consider a case where a thread calls a synchronized method f() on object A, and that method calls synchronized method g() on object A. Since the thread has already been granted the lock upon entering f(), it could not enter g() without reentrancy.

Reentrant Lock in Java

// Create a new Reentrant Lock
Lock lock = new ReentrantLock();
 
// try-finally block is not necessary
// but as this is a critical section,
// we want to ensure we unlock the lock
// regardless of whether the code executes
try {
	// Acquire lock
	lock.lock();
	
	// Only one thread can be here at a time
	// Mutate some variables, etc
} finally {
	// Release the lock
	lock.unlock();
}
 
// You can also try to acquire a lock and not block if there is a failure:
if (lock.tryLock()) {
	// We have the lock
}

Compared with synchronzied blocks:

  • A ReentrantLock can be made to give access to threads in the order they arrive to the critical section. The JVM has no guarantee on accessing synchronized blocks.
  • We can choose any number of acquisition policies.
  • The lock may provide information about what is waiting for it.