当前位置:网站首页>A lock faster than read-write lock. Don't get to know it quickly
A lock faster than read-write lock. Don't get to know it quickly
2022-07-27 22:02:00 【Huawei cloud developer Alliance】
Abstract : Let's talk about how to compare in a high concurrency environment ReadWriteLock Faster locks ——StampedLock.
This article is shared from Huawei cloud community 《【 High concurrency 】 A faster lock than read-write lock in high concurrency scenario , After reading it, I was completely convinced !!》, author : ice The river .
What is? StampedLock?
ReadWriteLock Locks allow multiple threads to read shared variables at the same time , But when reading shared variables , Other threads are not allowed to share variables for writing , More suitable for the environment of reading more and writing less . that , In an environment of more reading and less writing , Is there a better way than ReadWriteLock Faster locks ?
The answer, of course, is ! That's the protagonist we're going to introduce today ——JDK1.8 In the new StampedLock! you 're right , Is it !
StampedLock And ReadWriteLock comparison , In the process of reading, the following thread is also allowed to obtain the write lock and write to the shared variable , To avoid inconsistencies in the data read , Use StampedLock When reading shared variables , It is necessary to check whether the shared variables are written , And this kind of reading is an optimistic reading .
All in all ,StampedLock It's in the process of reading shared variables , Allow the following thread to acquire the write lock and write to the shared variable , Use optimistic reading to avoid data inconsistency , And in a high concurrency environment with more reading and less writing , Than ReadWriteLock A faster lock .
StampedLock Three lock modes
here , We can make a simple comparison StampedLock And ReadWriteLock,ReadWriteLock Supports two lock modes : One is read lock , The other is write lock , also ReadWriteLock Allow multiple threads to read shared variables at the same time , While reading , It is not allowed to write , When writing , You are not allowed to read , Reading and writing are mutually exclusive , therefore ,ReadWriteLock Read lock in , It's more about pessimistic lock reading .
StampedLock Three lock modes are supported : Write lock 、 Read the lock ( Read lock here refers to pessimistic read lock ) And optimistic reading ( Many materials and books are about optimistic reading lock , I think the more accurate one here is optimistic reading , Why? ? Let's keep looking down ). among , Write lock and read lock are related to ReadWriteLock The semantics in are similar to , Allow multiple threads to acquire read lock at the same time , But only one thread is allowed to get the write lock , Write lock and read lock are also mutually exclusive .
With another ReadWriteLock The difference is this :StampedLock After obtaining the read lock or write lock successfully , Will return to one Long Variable of type , And then when you release the lock , Need to pass in this Long Variable of type . for example , The logic shown in the following pseudo code demonstrates StampedLock How to acquire and release locks .
public class StampedLockDemo{
// establish StampedLock Lock object
public StampedLock stampedLock = new StampedLock();
// obtain 、 Release read lock
public void testGetAndReleaseReadLock(){
long stamp = stampedLock.readLock();
try{
// Execute the business logic after obtaining the read lock
}finally{
// Release the lock
stampedLock.unlockRead(stamp);
}
}
// obtain 、 Release the write lock
public void testGetAndReleaseWriteLock(){
long stamp = stampedLock.writeLock();
try{
// Execute the business logic after acquiring the write lock .
}finally{
// Release the lock
stampedLock.unlockWrite(stamp);
}
}
}StampedLock Support optimistic reading , It's more than ReadWriteLock The key to better performance . ReadWriteLock When reading shared variables , All writes to shared variables are blocked . and StampedLock Provide optimistic reading , When multiple threads read shared variables , Allow a thread to write to a shared variable .
Let's take another look JDK Official StampedLock Example , As shown below .
class Point {
private double x, y;
private final StampedLock sl = new StampedLock();
void move(double deltaX, double deltaY) { // an exclusively locked method
long stamp = sl.writeLock();
try {
x += deltaX;
y += deltaY;
} finally {
sl.unlockWrite(stamp);
}
}
double distanceFromOrigin() { // A read-only method
long stamp = sl.tryOptimisticRead();
double currentX = x, currentY = y;
if (!sl.validate(stamp)) {
stamp = sl.readLock();
try {
currentX = x;
currentY = y;
} finally {
sl.unlockRead(stamp);
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
void moveIfAtOrigin(double newX, double newY) { // upgrade
// Could instead start with optimistic, not read mode
long stamp = sl.readLock();
try {
while (x == 0.0 && y == 0.0) {
long ws = sl.tryConvertToWriteLock(stamp);
if (ws != 0L) {
stamp = ws;
x = newX;
y = newY;
break;
}
else {
sl.unlockRead(stamp);
stamp = sl.writeLock();
}
}
} finally {
sl.unlock(stamp);
}
}
}In the above code , If you are performing an optimistic read operation , Another thread writes to the shared variable , It will upgrade optimistic reading to pessimistic reading , The following code snippet shows .
double distanceFromOrigin() { // A read-only method
// Read optimistically
long stamp = sl.tryOptimisticRead();
double currentX = x, currentY = y;
// Determine whether a thread has written to a variable
// If a thread writes to a shared variable
// be sl.validate(stamp) Returns the false
if (!sl.validate(stamp)) {
// Upgrade optimistic read to pessimistic read lock
stamp = sl.readLock();
try {
currentX = x;
currentY = y;
} finally {
// Release pessimistic lock
sl.unlockRead(stamp);
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}This way of upgrading optimistic reading to pessimistic reading lock is more reasonable than that of using optimistic reading all the time , If you don't upgrade to pessimistic read lock , The program will repeatedly perform optimistic read operations in a loop , Until the optimistic read operation, no thread performs a write operation , And the constant execution of optimistic reading in the loop will consume a lot of CPU resources , Upgrading to pessimistic read lock is a more reasonable way .
StampedLock Realization thought
StampedLock The interior is based on CLH Lock implementation ,CLH It's a spin lock , Can guarantee that there is no “ Hunger ” Happen , And can guarantee FIFO( fifo ) The order of service .
stay CLH in , The lock maintains a queue of waiting threads , All application locks , But threads that fail will be put into this queue , Each node represents a thread , Save a marker bit (locked), Used to determine whether the current thread has released the lock , When locked The tag bit is true when , Indicates that the lock is acquired , When locked The tag bit is false when , Indicates that the lock has been released successfully .
When a thread tries to acquire a lock , Get the tail node of the waiting queue as its front node , And use a code similar to the following to determine whether the preorder node has successfully released the lock :
while (pred.locked) {
// Omit operation
}As long as the preorder node (pred) No release lock , Indicates that the current thread cannot continue execution , So it will spin and wait ; conversely , If the preamble thread has released the lock , Then the current thread can continue to execute .
When releasing the lock , And that's the logic , The thread will locked The location is marked as false, The thread waiting for it can continue to execute , That is, the lock has been released .
StampedLock On the whole , It's a little bit easier , Let's not talk about it here .
StampedLock Precautions for
In a high concurrency environment with more read and less write ,StampedLock It's really good , But it can't completely replace ReadWriteLock. In use , We also need to pay special attention to the following aspects .
StampedLock Reentry... Is not supported
you 're right ,StampedLock Reentry is not supported , in other words , In the use of StampedLock when , You can't nest , This should be paid special attention to when using .
StampedLock Conditional variables are not supported
The second thing to note is StampedLock Conditional variables are not supported , Whether it's a read lock or a write lock , Conditional variables are not supported .
StampedLock Improper use can lead to CPU soaring
This is also the most important point , Special attention should be paid when using : If a thread is blocked in StampedLock Of readLock() perhaps writeLock() When it comes to methods , At this point, call the interrupt() Method interrupt thread , It can lead to CPU Soar to 100%. for example , The following code shows .
public void testStampedLock() throws Exception{
final StampedLock lock = new StampedLock();
Thread thread01 = new Thread(()->{
// Get write lock
lock.writeLock();
// It's stuck here forever , Do not release the write lock
LockSupport.park();
});
thread01.start();
// Guarantee thread01 Get write lock
Thread.sleep(100);
Thread thread02 = new Thread(()->
// Blocking in pessimistic read lock
lock.readLock()
);
thread02.start();
// Guarantee T2 Blocking in the read lock
Thread.sleep(100);
// Interrupt threads thread02
// Will cause threads thread02 Where CPU soaring
thread02.interrupt();
thread02.join();
}Run the above program , It can lead to thread02 Where the thread is CPU Soar to 100%.
here , There are many friends who don't understand why LockSupport.park(); It can lead to thread01 It's going to block forever . here , Glacier draws you a life cycle diagram of threads , As shown below .

That makes sense ? In the life cycle of a thread , There are several important states that need to be explained .
- NEW: The initial state , Threads are built , But not yet called start() Method .
- RUNNABLE: Operational state , Runnable states can include : Running state and ready state .
- BLOCKED: Blocked state , The thread in this state needs to wait for other threads to release the lock or to enter synchronized.
- WAITING: Indicates a waiting state , The thread in this state needs to wait for other threads to notify or interrupt it , And then to the next state .
- TIME_WAITING: Timeout wait status . You can go back on your own at a certain time .
- TERMINATED: Termination status , The current thread has finished executing .
After reading the life cycle diagram of this thread , Know why to call LockSupport.park(); Can make thread02 It's blocked ?
therefore , In the use of StampedLock when , Be sure to avoid where the thread is CPU Soaring problems . So how to avoid ?
That's using StampedLock Of readLock() Method or read lock and use writeLock() Method to get the write lock , Do not call the thread interrupt method to interrupt the thread , If it's inevitable to interrupt the thread , Be sure to use StampedLock Of readLockInterruptibly() Method to get the interruptable read lock and use StampedLock Of writeLockInterruptibly() Method to get the interruptible pessimistic write lock .
Last , about StampedLock Use ,JDK Official StampedLock The example itself is a best practice , You guys can see more JDK Official StampedLock Example , Let's learn more about StampedLock How to use and behind the principle and core ideas .
Click to follow , The first time to learn about Huawei's new cloud technology ~
边栏推荐
- [question 23] Sudoku game with rotation | DFS (Beijing Institute of Technology / Beijing Institute of Technology / programming methods and practice / primary school)
- Log4j vulnerability is still widespread and continues to cause impact
- Finish learning redis cluster solution at one go
- Read Plato farm's eplato and the reason for its high premium
- Software testing interview question: when does the software testing project start? Why?
- First zhanrui 5g chip! Exposure of Hisense F50, a pure domestic 5g mobile phone: equipped with Huben T710 + chunteng 510
- 排序(冒泡排序)后面学习持续更新其它排序方法
- 哈希表的查找与插入及删除
- 内部类(四种内部类详解)
- 枚举和注解
猜你喜欢

@Component可以和@Bean 用在同一个类上吗?

8000字讲透OBSA原理与应用实践

Search, insert and delete of hash table

2022 2nd cyber edge cup cyber security competition Web

除了「加机器」,其实你的微服务还能这样优化

LVS+Keepalived高可用群集

Pytoch distributed training

JVM garbage collection garbage collector and common combination parameters
Excalidraw: an easy-to-use online, free "hand drawn" virtual whiteboard tool

异常-Exception
随机推荐
Recursion / backtracking (Part 1)
Commercial delay of self-developed 5g chip? Apple iPhone will adopt Qualcomm 5g chip in the next four years
MySQL data recovery process is based on binlog redolog undo
day 1 - day 4
Shengyang technology officially launched the remote voiceprint health return visit service system!
Form of objects in memory & memory allocation mechanism
Monitor the running of server jar and restart script
Log4j 漏洞仍普遍存在?
Implementation of arbitrary code execution based on.Net dynamic compilation technology
V2.x synchronization is abnormal. There are a lot of posts that cannot be synchronized in the cloud, and the synchronization is blocked and slow
如何实现一个好的知识管理系统?
@Can component be used on the same class as @bean?
[question 23] Sudoku game with rotation | DFS (Beijing Institute of Technology / Beijing Institute of Technology / programming methods and practice / primary school)
@Detailed introduction of requestparam annotation
Why do server programs need to listen first
Inertial navigation principle (VII) -imu error classification (II) -allan variance analysis method +imu test + calibration introduction
C language output teaching calendar
哈希表的查找与插入及删除
Go language learning notes - mutex start go language from scratch
成员方法及其传参机制