Read write lock analysis

Posted by franklyn on Tue, 08 Feb 2022 12:41:15 +0100

Tip: after the article is written, the directory can be generated automatically. Please refer to the help document on the right for how to generate it

preface

Multithreading is one of the cores of java. As a java Engineer, you must understand multithreading thoroughly!

Tip: the following is the main content of this article. The following cases can be used for reference

1, Basic concepts of read-write lock

1) First, read-write locks are mutually exclusive. They cannot exist in the same resource of a thread at the same time (for example, there are read locks and write locks in a method at the same time, because the method is called with the help of an object, the lock granularity is an object, and they are mutually exclusive, so they cannot exist at the same time). Otherwise, deadlock will occur.

2) When a thread obtains a read lock of a resource, other threads cannot obtain a write lock of the resource (the resource can be abstracted as an object, which is easier to understand), but it can obtain a read lock. The read lock here can be abstracted as not locking for the read operation.

3) When a thread obtains the write lock of a resource, other resources cannot obtain the read lock and write lock of the resource (to prevent dirty reading)

4) for example, a class A has three methods, B(), C(), D(), where B() adds the write lock, C() adds the read lock, D() method calls B() and C() method, this time will inevitably happen deadlock, because mutual exclusion.

2, Code example

1. Call read lock and write lock at the same time

The code is as follows (example):

class MyCache{
    Map<String,Object> map=new HashMap<>();
    ReadWriteLock readWriteLock=new ReentrantReadWriteLock();
    public void put(String key,Object V){
        try {
        	//Method of adding write lock
            readWriteLock.writeLock().lock();
            map.put(key, V);
        }catch (Exception e){
            System.out.println(e.getStackTrace());
        }finally {
            readWriteLock.writeLock().unlock();
        }

    }


    public void get(int key,Object V){

        try {

            readWriteLock.readLock().lock();//Read lock added
            System.out.println(Thread.currentThread().getName() + "About to write");
            this.put(String.valueOf(key*3),V);//Write lock added
            System.out.println(Thread.currentThread().getName() + "Write complete");

            System.out.println(Thread.currentThread().getName()+"About to read");
            map.get(key); //Read lock added
            System.out.println(Thread.currentThread().getName()+"Read complete");

        }catch (Exception e){
            System.out.println(e.getStackTrace());
        }finally {
            readWriteLock.readLock().unlock();
        }
    }
}

main thread:

public class Lock01 {

    public static void main(String[] args) {
        MyCache myCache=new MyCache();
        
        for (int i=0;i<5;i++) {
            int finalI = i;
            new Thread(() -> {
                myCache.get(finalI,finalI*3);
            }).start();
        }
    }
}

Result: a deadlock occurs, causing a blockage

F:\jdk11.06\bin\java.exe "
Thread-0 About to write
Thread-1 About to write

2. Read locks can be compatible with each other

The code is as follows (example):

class MyCache{
    Map<String,Object> map=new HashMap<>();
    ReadWriteLock readWriteLock=new ReentrantReadWriteLock();
    public void put(String key,Object V){
        try {
            readWriteLock.readLock().lock();
            map.put(key, V);
        }catch (Exception e){
            System.out.println(e.getStackTrace());
        }finally {
            readWriteLock.readLock().lock();
            System.out.println("");
        }
    }


    public void get(int key,Object V){

        try {

            readWriteLock.readLock().lock();
            System.out.println(Thread.currentThread().getName() + "About to write");
            this.put(String.valueOf(key*3),V);//Read lock added
            System.out.println(Thread.currentThread().getName() + "Write complete");


            System.out.println(Thread.currentThread().getName()+"About to read");
            map.get(key); //Read lock added
            System.out.println(Thread.currentThread().getName()+"Read complete");

        }catch (Exception e){
            System.out.println(e.getStackTrace());
        }finally {
            readWriteLock.readLock().unlock();
        }
    }
}

Results: without blocking, multiple threads can obtain read locks

Thread-2 About to write
Thread-4 About to write

Thread-3 About to write
Thread-1 About to write
Thread-0 About to write

Thread-0 Write complete
Thread-0 About to read
Thread-0 Read complete

Thread-1 Write complete
Thread-1 About to read
Thread-1 Read complete

Thread-3 Write complete
Thread-3 About to read
Thread-3 Read complete
Thread-2 Write complete
Thread-2 About to read
Thread-2 Read complete

Thread-4 Write complete
Thread-4 About to read
Thread-4 Read complete

Process finished with exit code 0

summary

The concept of read-write lock can be understood with the help of mysql. When the granularity of the lock is a table, if this table has a read lock, all threads can read but cannot write. When a write lock is added, other threads cannot write or read. They can only wait for the thread that obtains the write lock to release the lock.

Topics: Java Back-end Multithreading