Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand locks in Java

2025-02-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article will explain in detail how to understand the locks in Java. The content of the article is of high quality, so the editor shares it for you as a reference. I hope you will have some understanding of the relevant knowledge after reading this article.

ReadWriteLock interface

Read-write locks maintain a pair of associated locks, one for read operations and one for write operations. Read locks can be held by multiple threads at the same time, also known as shared locks. A write lock can only be held by one thread at a time, also known as a mutex. At the same time, two locks cannot be held by different threads. Read-write locks are suitable for scenarios where read operations are more than write operations, and improve the performance of mutexes, such as concurrent security modification of collections, cache components, and so on.

Analysis of the principle of ReentrantReadWriteLock implementation

ReentrantReadWriteLock needs an owner to mark that the thread of the write operation acquired the lock, owner marks only the thread reference of the write operation, not the thread of the read operation, a writeCount is used to record the number of times the write operation is locked, a readCount is used to record the number of times the read operation is locked, and an waiters wait queue is used to store the list of threads that did not grab the lock

When a write thread comes in, the value of readCount will be judged first. If readCount is 0, the read lock is not occupied.

Then judge the value of writeCount. If writeCount is 0, the write lock is not occupied.

Then add 1 to the writeCount value through the CAS operation, and set the owner to the reference of the current write thread if the lock is grabbed

If writeCount is not 0 and owner refers to the current writer thread, add 1 to the value of writeCount

If writeCount is not 0 and owner points to a reference that is not the current writer thread, the thread is placed in the waiting queue

If CAS fails to grab the lock, put the thread in the waiting queue

If the readCount is not 0 indicating that the read lock is occupied when the write thread comes in, put the thread in the waiting queue

When a read operation thread comes in, it will first judge the value of writeCount. If writeCount is 0, the write lock is not occupied.

Then add 1 to the value of readCount through CAS

If the read thread comes in, writeCount does not have a 0 indicating that the write lock is occupied

If the write lock is occupied by the current thread, the thread can continue to acquire the read lock, that is, the lock degradation

If the write lock is not occupied by the current thread, put the thread in the waiting queue

When a write thread releases the lock, the value of writeCount will be subtracted by 1. If the value of writeCount is 0, owner will be set to null and the thread waiting for the queue head will be awakened to grab the lock.

If the header thread of the waiting queue is a read operation, the CAS operation increments the readCount value by 1 and wakes up the next waiting thread

If the next thread is still a read operation, the CAS operation increments the readCount value by 1 and continues to wake up the next waiting thread

If the next thread is a write operation, it will not wake up until the read lock has been released

Manual implementation of ReentrantReadWriteLock example:

Public class MyReadWriteLock {private AtomicInteger readCount = new AtomicInteger (0); private AtomicInteger writeCount = new AtomicInteger (0); / / exclusive lock owner private AtomicReference owner = new AtomicReference (); / / wait queue private volatile LinkedBlockingQueue waiters = new LinkedBlockingQueue (); class WaitNode {int type = 0; / / 0 is the thread that wants to acquire the exclusive lock, 1 is the thread that wants to acquire the shared lock Thread thread = null; int arg = 0 Public WaitNode (Thread thread, int type, int arg) {this.thread = thread; this.type = type; this.arg = arg;}} / / acquire the exclusive lock public void lockWrite () {int arg = 1; / / attempt to acquire the exclusive lock, if successful, exit the method, if failed. If (! tryLockWrite (arg)) {/ / marked as exclusive lock WaitNode waitNode = new WaitNode (Thread.currentThread (), 0, arg); waiters.offer (waitNode); / / enter the waiting queue / / Loop attempt to take the lock for (;;) {/ / if the queue header is the current thread WaitNode head = waiters.peek () If (head! = null & & head.thread = = Thread.currentThread ()) {if (! tryLockWrite (arg)) {/ / attempt to acquire exclusive lock LockSupport.park () again; / / if failed, suspend thread} else {/ / if successfully acquire waiters.poll (); / / remove return from queue header for the current thread / / and exit method} else {/ / if it is not the queue header element LockSupport.park (); / / suspend the current thread} / / release the exclusive lock public boolean unlockWrite () {int arg = 1; / / attempt to release the exclusive lock returns true if it fails. If (tryUnlockWrite (arg)) {WaitNode next = waiters.peek (); / / take out the element if (next! = null) {Thread th = next.thread; LockSupport.unpark (th) in the queue header; / / wake up the thread in the queue header} return true; / / return true} return false } / / attempt to acquire the exclusive lock public boolean tryLockWrite (int acquires) {/ / if read count! = 0 returns false if (readCount.get ()! = 0) return false; int wct = writeCount.get (); / / gets the current state of the exclusive lock if (wct = = 0) {if (writeCount.compareAndSet (wct, wct + acquires)) {/ / grabs the lock owner.set (Thread.currentThread ()) by modifying state; / / after grabbing the lock, directly modify owner to the current thread return true }} else if (owner.get () = = Thread.currentThread ()) {writeCount.set (wct + acquires); / / modify the count value return true;} return false;} / / attempt to release the exclusive lock public boolean tryUnlockWrite (int releases) {/ / if the current thread does not have an exclusive lock if (owner.get ()! = Thread.currentThread ()) {throw new IllegalMonitorStateException () / / throw IllegalMonitorStateException} int wc = writeCount.get (); int nextc = wc-releases; / / calculate the remaining occupancy of the exclusive lock writeCount.set (nextc); / / update the count value if (nextc = = 0) {/ / whether owner.compareAndSet (Thread.currentThread (), null) is fully released or not; return true;} else {return false }} / / acquire the shared lock public void lockRead () {int arg = 1; if (tryLockRead (arg))

< 0) { // 如果tryAcquireShare失败 // 将当前进程放入队列 WaitNode node = new WaitNode(Thread.currentThread(), 1, arg); waiters.offer(node); // 加入队列 for (; ; ) { // 若队列头部的元素是当前线程 WaitNode head = waiters.peek(); if (head != null && head.thread == Thread.currentThread()) { if (tryLockRead(arg) >

= 0) {/ / attempt to acquire the shared lock, if successful waiters.poll (); / / remove the current thread from the queue WaitNode next = waiters.peek (); if (next! = null & & next.type = = 1) {/ / if the next thread is also waiting for the shared lock LockSupport.unpark (next.thread) / / Wake it up} return; / / exit method} else {/ / if the attempt fails LockSupport.park (); / / suspend thread}} else {/ / if it is not the header element LockSupport.park () } / / unlock shared lock public boolean unLockRead () {int arg = 1; if (tryUnLockRead (arg)) {/ / release share success WaitNode next = waiters.peek () when read count becomes 0; if (next! = null) {LockSupport.unpark (next.thread);} return true;} return false } / / attempt to acquire shared lock public int tryLockRead (int acquires) {for (;;) {if (writeCount.get ()! = 0 & & owner.get ()! = Thread.currentThread ()) return-1; int rct = readCount.get (); if (readCount.compareAndSet (rct, rct + acquires)) {return 1 } / / attempt to unlock shared lock public boolean tryUnLockRead (int releases) {for (;;) {int rc = readCount.get (); int nextc = rc-releases; if (readCount.compareAndSet (rc, nextc)) {return nextc = = 0;} lock degradation

Lock degradation refers to the degradation of a write lock to a read lock, which means that while holding the write lock, the read lock is acquired, and then the write lock is released. The write lock is exclusive to the thread and the read lock is shared by the thread, so it is feasible to downgrade the write lock to the read lock, but it is not feasible to upgrade the read lock to the write lock.

Code example:

Class TeacherInfoCache {static volatile boolean cacheValid; static final ReadWriteLock rwl = new ReentrantReadWriteLock (); static Object get (String dataKey) {Object data = null; / / read data with read lock rwl.readLock (). Lock (); try {if (cacheValid) {data = Redis.data.get (dataKey);} else {/ / access DB by locking, write lock rwl.readLock (). Unlock () Rwl.writeLock (). Lock (); try {if (! cacheValid) {data = DataBase.queryUserInfo (); Redis.data.put (dataKey, data); cacheValid = true;}} finally {/ / Lock downgrade rwl.readLock () .lock (); rwl.writeLock () .unlock () }} return data;} finally {rwl.readLock (). Unlock ();} class DataBase {static String queryUserInfo () {System.out.println ("query database.") ; return "name:Kody,age:40,gender:true,";}} class Redis {static Map data = new HashMap ();} so much about how to understand locks in Java. I hope the above can help you and learn more. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report