preface

In concurrent programming, locking is often used. Today we will look at the locking mechanisms in Java: synchronized and lock.

The concept of Synchronized and Lock

Synchronized is an important keyword in Java concurrent programming. Another important keyword is volatile.

The purpose of syncronization is to allow only one thread at a time to enter the code snippet it decorates, thus allowing them to protect themselves. Synchronized is a lot like the real-life lock example. Entering a code area protected by Synchronized first requires acquiring the Synchronized lock, and other threads must wait to execute it. Synchronized areas of code that are locked need to be returned, or released, after execution, so that they can be used by other threads.

Lock is a very important interface in Java concurrent programming, it can be more literal than Synchronized keyword “Lock” concept, Lock needs to manually Lock and manually unlock, generally through the lock. Lock () method to Lock, Use the lock.unlock() method to unlock it. Locks closely associated with Lock are ReetrantLock and ReadWriteLock.



ReetrantLock implements the Lock interface, which is a reentrant Lock that internally defines fair and unfair locks.

ReadWriteLock One is used to obtain read locks and one is used to obtain write locks. This means that the read and write operations of the file are divided into two locks and assigned to the thread, so that multiple threads can read at the same time. ReentrantReadWirteLock implements the ReadWirteLock interface but not the Lock interface.

Use of Synchronized and Lock

Use of Synchronized and Lock:

Here is an example of Synchronized:

Use Synchronized for methods

After the scope operator and before the return type declaration. That is, only one thread can enter the method at a time, and other threads have to queue up to call the method at that time.

private int number;
public synchronized void numIncrease(){
  number++;
}

Copy the code

Use Synchronized in a section of code

You can also use the Synchronized keyword on a block of code to indicate that only one thread can enter a section of code.

public void numDecrease(Object num){ synchronized (num){ number++; }}Copy the code

Use Synchronized to lock the entire object

Synchronized is followed by an object in parentheses, and the thread acquires the object lock.

public void test() { synchronized (this) { // ... }}Copy the code
Here is an example of a Lock:

Lock is an interface that consists mainly of the following methods

public interface Lock {
    void lock();
    void lockInterruptibly() throws InterruptedException;
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    void unlock();
    Condition newCondition();
}

Copy the code
A simple explanation of the Lock interface method above:

Lock (): The lock method is probably the most commonly used method to obtain the lock. If the lock is acquired by another thread, it waits.

If a Lock is used, the Lock must be actively released and will not be automatically released in the event of an exception.

Lock lock = ... ; lock.lock(); Try {// process tasks}catch(Exception ex){}finally{lock.unlock(); // release the lock}Copy the code
TryLock () : The method returns a value indicating that it was used to attempt to acquire the lock, returning true on success or false on failure (i.e. the lock has been acquired by another thread), meaning that the method will return immediately anyway. You don’t wait around until you get the lock.

The tryLock(long time, TimeUnit Unit) method is similar to the tryLock() method, except that it waits a certain amount of time before the lock is available and returns false if the lock is not available within the time limit. Returns true if the lock was acquired initially or during the wait.

Lock lock = ... ;if(lock.trylock ()) {try{// process tasks}catch(Exception ex){}finally{lock.unlock(); // Release the lock}}else{// If you can't get the lock, just do something else}Copy the code
LockInterruptibly () : This method is special in that if the thread is waiting to acquire the lock while the lock is being acquired, the thread can respond to interrupts, the wait state of the interrupted thread. That is, when two threads attempt to acquire A lock using lock.lockinterruptibly () at the same time, A call to threadb.interrupt () on threadB interrupts the wait if thread A has acquired the lock while threadB is waiting.

Since the lockInterruptibly() declaration threw an exception, So lock.lockInterruptibly() must be placed in a try block or declare that InterruptedException is thrown outside the method that calls lockInterruptibly(). The general form is as follows:

public void method() throws InterruptedException { lock.lockInterruptibly(); try { //..... } finally { lock.unlock(); }}Copy the code
In general, using a Lock must be done ina try{}catch{} block, and the Lock release must be done ina finally block to ensure that the Lock is always released and to prevent deadlocks.

Note that once a thread has acquired the lock, it is not interrupted by the interrupt() method. This is because, as I explained in an earlier article, calling interrupt() alone cannot interrupt a running thread, only a blocking thread. Therefore, when a lock is obtained using the lockInterruptibly() method, if it is not obtained, the interrupt can be responded to only by waiting. Synchronized means that a thread that is waiting for a lock cannot be interrupted.


The main differences between Synchronized and Lock

The main differences between Synchronzied and Lock are as follows:

  • Existential level: Syncronized is a Java keyword that exists at the JVM level, and Lock is an interface in Java
  • The lock release conditions are as follows: 1. The lock is automatically released after the thread that obtains the lock completes the synchronization code. 2. When an exception occurs, the JVM causes the thread to release the lock. Lock must release the Lock in the finally keyword, otherwise thread deadlocks are likely
  • Lock acquisition: In Syncronized, it is assumed that thread A acquires the lock and thread B waits. If A is blocked, then B will wait. In a Lock, it depends on the situation, there is a method to try to get the Lock, if you try to get the Lock, you don’t have to wait
  • Synchronized cannot identify the Lock status, whereas Lock can identify the Lock status
  • Synchronized is a reentrant, non-interruptible, non-fair lock. Lock is reentrant, judge, fair Lock
  • Lock performance: Synchronized is suitable for a small amount of synchronization and has high performance overhead. Lock Locks are suitable for a large number of synchronization phases:
  • Lock locks make multiple threads read more efficiently (using readWriteLock)
  • When the competition is not very fierce, the performance of Synchronized is better than that of ReetrantLock, but when the competition is very fierce, the performance of Synchronized will decrease by dozens of times, but the performance of ReetrantLock can maintain the normal;
  • ReetrantLock provides a variety of synchronization options, such as time-limited synchronization, Interrupt synchronization, and so on.


The last

Welcome to pay attention to my public number [programmer chasing wind], the article will be updated in it, sorting out the data will be placed in it.