This article mainly introduces reentrancy locks and read-write locks in Java concurrent programming. The relevant example codes in the article are detailed and available for testing. It has certain reference value. Friends who need it can learn more.
Reentrancy lock
Reentrancy lock, as the name suggests, is a lock that supports reentry. It means that the lock can support repeated locking of resources by a thread. Re-entry means that any thread can acquire the lock again without being blocked by the lock after acquiring the lock. The implementation of this feature needs to solve the following two problems.
1. The thread acquires the lock again. The lock needs to identify whether the thread acquiring the lock is the thread currently occupying the lock. If so, it can be acquired successfully again.
2. The final release of the lock. The thread acquires the lock repeatedly n times, and then after releasing the lock for the nth time, other threads can acquire the lock. The final release of the lock requires the lock to increment the count for acquisition. The count indicates the number of times the current lock has been repeatedly acquired. When the lock is released, the count decrements. When the count equals 0, it means that the lock has been successfully released.
The built-in lock (synchronize) and Lock (ReentrantLock) in Java are both reentrant
##synchronized examples
package com.home; public class SynchronizedTest implements Runnable { public synchronized void method1() { System.out.println("method1获得锁,正常运行!"); method2(); } public synchronized void method2() { System.out.println("method2获得锁,也正常运行!"); } @Override public void run() { method1(); } public static void main(String[] args) { SynchronizedTest st = new SynchronizedTest(); new Thread(st).start(); new Thread(st).start(); } }
#Lock Example
package com.home; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockTest implements Runnable { Lock lock = new ReentrantLock(); public void method1() { lock.lock(); System.out.println("method1获得锁,正常运行!"); method2(); lock.unlock(); } public void method2() { lock.lock(); System.out.println("method2获得锁,也正常运行!"); lock.unlock(); } @Override public void run() { method1(); } public static void main(String[] args) { LockTest lt = new LockTest(); new Thread(lt).start(); new Thread(lt).start(); } }The final results of both examples are correct, the results are as follows:
method1获得锁,正常运行! method2获得锁,也正常运行! method1获得锁,正常运行! method2获得锁,也正常运行!
The biggest role of reentrant lock is to avoid deadlock
Read-write lock
The read-write lock maintains a pair of related locks, one for read-only operations and one for write operations. As long as there is no writer, the read lock can be held by multiple reader threads simultaneously. Write locks are exclusive.Reentrant ReadWriteLock ReentrantReadWriteLock
package com.home; import java.util.Random; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; class ReadWrte { // 共享数据,可以多个线程读数据,只能有一个线程写数据 private int data; // 创建读写锁 ReadWriteLock rwLock = new ReentrantReadWriteLock(); /** * 读数据,上读锁 */ public void get() { // 读锁 rwLock.readLock().lock(); try { System.out.println(Thread.currentThread().getName() + ",Read!"); Thread.sleep((long) Math.random() * 1000); System.out.println(Thread.currentThread().getName() + " 读出的数据为:" + this.getData()); } catch (Exception e) { e.printStackTrace(); } finally { rwLock.readLock().unlock(); } } /** * 写数据,上写锁 * * @param data */ public void put(int data) { // 写锁 rwLock.writeLock().lock(); try { System.out.println(Thread.currentThread().getName() + ",Write!"); Thread.sleep((long) Math.random() * 1000); this.setData(data); System.out.println(Thread.currentThread().getName() + " 写入的数据为:" + this.getData()); } catch (InterruptedException e) { e.printStackTrace(); } finally { rwLock.writeLock().unlock(); } } public int getData() { return data; } public void setData(int data) { this.data = data; } } /** * 测试类 * * @author itmyhome * */ public class ReadWriteLockTest { /** * @param args */ public static void main(String[] args) { // 创建ReadWrte对象 final ReadWrte rw = new ReadWrte(); for (int i = 0; i < 10; i++) { // 创建并启动10个读线程 new Thread(new Runnable() { @Override public void run() { rw.get(); } }).start(); // 创建并启动10个写线程 new Thread(new Runnable() { @Override public void run() { // 写入一个随机数 rw.put(new Random().nextInt(8)); } }).start(); } } }The output is
Thread-0,Read! Thread-4,Read! Thread-8,Read! Thread-12,Read! Thread-0 读出的数据为:0 Thread-4 读出的数据为:0 Thread-8 读出的数据为:0 Thread-12 读出的数据为:0 Thread-19,Write! Thread-19 写入的数据为:5 Thread-7,Write! Thread-7 写入的数据为:7 Thread-3,Write! Thread-3 写入的数据为:4 Thread-16,Read! Thread-16 读出的数据为:4 Thread-11,Write! Thread-11 写入的数据为:0 Thread-15,Write! Thread-15 写入的数据为:5 Thread-2,Read! Thread-2 读出的数据为:5 Thread-17,Write! Thread-17 写入的数据为:2 Thread-6,Read! Thread-6 读出的数据为:2 Thread-1,Write! Thread-1 写入的数据为:5 Thread-13,Write! Thread-13 写入的数据为:4 Thread-9,Write! Thread-9 写入的数据为:7 Thread-5,Write! Thread-5 写入的数据为:2 Thread-10,Read! Thread-10 读出的数据为:2 Thread-18,Read! Thread-14,Read! Thread-18 读出的数据为:2 Thread-14 读出的数据为:2We can see from the picture that multiple threads can read at the same time, but only one thread can write, that is, writing data and writing data are completed at the same time.
Summarize
The above is the detailed content of Detailed explanation of reentrancy locks and read-write locks in Java concurrency. For more information, please follow other related articles on the PHP Chinese website!