Differences between Java--synchronized and Lock and examples of their use

1. Classification of Java locks (reference link: https://tech.meituan.com/2018/11/15/java-lock.html )

(1) Optimistic lock VS pessimistic lock:

* * optimistic Lock: * * Lock the data first to ensure that the data will not be modified by other threads. The synchronized keyword and the implementation class of Lock are pessimistic locks. It is suitable for scenarios with frequent write operations.

* * pessimistic lock: * * only judge whether another lock has updated the data when updating the data. If so, perform operations such as error reporting or automatic retry. Otherwise, write the modified data directly. It is suitable for scenes with frequent read operations.

(2) Fair lock VS non fair lock

* * FAIR lock: * * multiple threads acquire locks in the order in which they apply for locks.

* * unfair Lock: * * when multiple threads Lock, they directly try to obtain the Lock. If the Lock is just available at this time, the thread does not need to block to obtain the Lock directly, otherwise it waits at the end of the waiting queue. ReentrantLock (implementation class of Lock) uses non fair Lock by default, but fair Lock can be specified through constructor.

(3) Reentrant lock VS non reentrant lock

* * reentrant lock: * * for example, when a thread executes a synchronized method, such as method1(), and another synchronized method method2() will be called in method1(), the thread can directly execute method2() without re applying for the lock (provided that the lock object is the same object or class). The example code is as follows:

class MyClass {
    public synchronized void method1() {
        method2();
    }

    public synchronized void method2() {

    }
}

(4) Interruptible lock VS non interruptible lock

* * interruptible lock: * * it can be interrupted while waiting to obtain the lock. For example, thread B is waiting for thread A to release the lock. Thread B can actively interrupt the waiting lock because the waiting time is too long.

(5) Read write lock

The reading and writing of resources are divided into two parts. The read lock is used to ensure that multiple threads can read resources synchronously, and the write lock is used to ensure the synchronization of data writing. ReadWriteLock is a read-write lock. Read lock is obtained through readLock(), and write lock is obtained through writeLock().

2. The difference between synchronized and Lock

synchronizedLock
Existence hierarchyjava keyword, at the jvm levelOne interface
Lock acquisitionSuppose that thread A obtains the lock and thread B waits. If thread A is blocked, thread B will wait all the time.You can try to acquire the lock. If the acquisition is successful, the thread does not have to wait all the time (you can judge whether there is a lock through tryLock)
Lock release1. The thread that obtains the lock executes the synchronization code and releases the lock; 2. If an exception occurs during thread execution, the jvm will let the thread release the lockThe Lock must be released in finally, otherwise it is easy to cause thread deadlock (generally speaking, the use of Lock must be carried out in the try{}catch {} block, and the operation of releasing the Lock must be carried out in the finally block to ensure that the Lock must be released to prevent deadlock)
Lock statusUnable to judgeCan judge
Type of lockReentrant, non interruptible, unfairReentrant, interruptible, fair / unfair

Usage comparison:

  • Lock must acquire and release the lock manually, while synchronized does not need to release and open the lock manually;
  • Lock is only applicable to code block locks, while synchronization D can be used to decorate methods, code blocks, etc.

Performance comparison:

  • Lock can improve the efficiency of reading operations by multiple threads (read-write separation can be realized through ReadWriteLock);
  • When the resource competition is not very fierce, the performance of synchronized is due to ReetrantLock, but when the resource competition is very fierce, the performance of synchronized will be reduced by dozens of times, but the performance of ReetrantLock can remain normal.

3. Use example

(1) synchronized (reference link: https://blog.csdn.net/luoweifu/article/details/46613015 )

Modified static method

//Synchronous thread
class SyncTHread implements Runnable{
    private static int number;

    public SyncTHread(){
        number=0;
    }

    public synchronized static void method(){
        for (int i=0;i<5;i++){
            try {
                System.out.println(Thread.currentThread().getName()+": "+(number++));
                Thread.sleep(100);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }

    public synchronized void run(){
        method();
    }
}
//test
public class testSynThread {
    public static void main(String[] args) {
        SyncTHread syncTHread1 = new SyncTHread();
        SyncTHread syncTHread2 = new SyncTHread();
        Thread thread1 = new Thread(syncTHread1, "SyncThread1");
        Thread thread2 = new Thread(syncTHread2, "SyncThread2");
        thread1.start();
        thread2.start();
    }
}
//Operation results
SyncThread1: 0
SyncThread1: 1
SyncThread1: 2
SyncThread1: 3
SyncThread1: 4
SyncThread2: 5
SyncThread2: 6
SyncThread2: 7
SyncThread2: 8
SyncThread2: 9

In the test code, syncThread1 and syncThread2 are two objects of SyncThread, but when thread1 and thread2 execute concurrently, they keep thread synchronization, because run() calls static method method(), while synchronized modified static method locks all objects of this class, so syncThread1 and syncThread2 are equivalent to using the same lock.

(2)lock

class LockThread implements Runnable{
    private static int number;
    private ReentrantLock lock=new ReentrantLock();

    public LockThread(){
        number=0;
    }

    public void method(){
        try {
            lock.lock();
            for (int i=0;i<5;i++){
                System.out.println(Thread.currentThread().getName()+": "+(number++));
                Thread.sleep(100);
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }


    public void run(){
        method();
    }
}

//test
public class testLock{
    public static void main(String[] args) {
        LockThread lockThread1 = new LockThread();
        LockThread lockThread2 = new LockThread();
        Thread thread1 = new Thread(lockThread1, "lockThread1");
        Thread thread2 = new Thread(lockThread2, "lockThread2");
        thread1.start();
        thread2.start();
    }
}
//Operation results
lockThread1: 0
lockThread2: 1
lockThread1: 2
lockThread2: 2
lockThread2: 3
lockThread1: 4
lockThread1: 5
lockThread2: 5
lockThread2: 6
lockThread1: 7

Keywords: Java lock synchronized

Added by deepakagrawal1982 on Sat, 26 Feb 2022 05:43:46 +0200