Cartoon: from JVM lock to redis distributed lock

bravo1988 2021-05-04 14:48:21
cartoon jvm lock redis distributed

No matter in the interview or in the actual work ,Redis It's all technical points that can't be avoided . In my heart ,MySQL and Redis It's a measure of whether a programmer “ A small success ” The two rulers of . If he can use it skillfully MySQL and Redis, Small to big , Make full use of existing resources to meet current needs , It means he has grown up .

This article will start with JVM Of synchronized、ReentrantLock Talk about Redis Distributed lock , No specific code implementation is involved , But in simple terms, it introduces the idea and general principle , Very friendly to Xiaobai ~

JVM lock

So-called JVM lock , Actually, it means something like synchronized Keywords or ReentrantLock Implemented locks . It's called JVM lock , It's because our projects are actually running in JVM Upper . In theory, after every project starts , It corresponds to a piece of JVM Memory , The life and death of the subsequent runtime data are all in this land .

 picture .png

What is a lock 、 How to lock it ?

got it “JVM lock ” The origin of the name , Let's talk about “ lock ”, And how “ lock ”.

Sometimes it's hard to explain what something is , But it's easy to explain what it does ,JVM Lock is the same thing .JVM The appearance of lock , To solve the problem of thread safety . The so-called thread safety problem , It can be simply understood as data inconsistency ( Not in line with expectations ).

When might a thread safety problem occur ?

When the following three conditions are met simultaneously , Can cause thread safety problems :

  • Multithreaded environment
  • There's shared data
  • There are multiple statement operations that share data / A single statement itself is not an atomic operation ( such as i++ Although it's a single statement , But it's not atomic )

Like threads A、B At the same time int count Conduct +1 operation ( The initial value is assumed to be 1), Under certain probability, the final result of two operations may be 2, instead of 3.

 picture .png

So why can locking solve this problem ?

If you don't consider atomicity 、 Memory barrier and other obscure terms , The reason why locking can ensure thread safety , The core is “ Mutually exclusive ”. So called mutual exclusion , It's literally mutually exclusive . there “ each other ” Who do you mean ? Between threads !

How to realize the mutual exclusion between multithreads ?

introduce “ A middleman ” that will do .

Be careful , It's a very simple and great idea . In the programming world , By introducing “ The mediation ” There are so many cases to solve the problem , Including but not limited to Spring、MQ. Between manors , There is even a saying that : There is no problem that can't be solved by introducing the middle layer .

and JVM A lock is actually a thread and a thread to each other “ A middleman ”, Multiple threads must ask for information before operating on the locked data “ A middleman ” Consent of :

 picture .png

Lock's role here is actually goalkeeper , It's the only access , All threads have to go through its torture . stay JDK in , There are two most common lock implementation mechanisms , There are two factions :

  • synchronized keyword
  • AQS

Personally feel synchronized Keywords are better than AQS Hard to understand , but AQS The source code is more abstract . Here is a brief introduction Java Object memory structure and synchronized The implementation principle of keywords .

Java Object memory structure

To understand synchronized keyword , The first thing to know is Java Object's memory structure . Once again , yes Java Object's Memory structure .

Its existence seems to throw us a question : If you have a chance to dissect one Java object , What can we see ?

 picture .png

Two objects are drawn on the top right , Just look at one of them . We can observe that ,Java Object memory structure is roughly divided into several blocks :

  • Mark Word( Lock related )
  • Metadata pointer (class pointer, Point to the class to which the current instance belongs )
  • The instance data (instance data, This is the only piece we usually see )
  • alignment (padding, It's about memory alignment )

If you haven't known before Java Object's memory structure , You may be surprised : Oh, my God , I thought Java Objects have only properties and methods !

Yes , We are most familiar with instance data , And I thought it was the only one . It is also the limitation of this concept , Some beginners are hard to understand synchronized. For example, beginners often wonder :

  • Why any object can be used as a lock ?
  • Object What's the difference between object locks and class locks ?
  • synchronized What is the lock used in the common way of decorating ?
  • synchronized What is the lock used by the decorated static method ?

All of this , In fact, it can be in Java Object memory structure Mark Word Find out :

 picture .png

Many students may see this picture for the first time , I feel a little confused , No problem , I have a big head, too , It's all the same .

Mark Word It contains a lot of information , But here we just need to understand it as a mark to record the lock information . The picture above shows 32 Under virtual machine Java Object memory , If you count carefully , You'll find it all bit It just adds up to 32 position .64 The structure of virtual machine is similar , No special introduction .

Mark Word From the Limited 32bit Mark out 2bit, It is specially used as a lock mark bit , Generally speaking, it is to mark the status of the current lock .

 picture .png

Because of every Java Object has Mark Word, and Mark Word Can mark lock status ( Think of yourself as a lock ), therefore Java Any object in can be used as synchronized Lock of :

 Copy code 

So-called this The lock is the current object , and Class A lock is the class to which the current object belongs Class object , Essence is also Java object .synchronized The common way to modify is to use the current object as a lock ,synchronized Modify the static method underlying use Class Object as lock .

But if you want to ensure that multiple threads are mutually exclusive , The basic condition is that they Use the same lock :

 picture .png

It doesn't make sense to put two different locks on the same piece of data , In actual development, we should pay attention to avoid the following writing :

// operation count
// operation count
 Copy code 


public synchronized void method1(){
// operation count
public static synchronized void method1(){
// operation count
 Copy code 

synchronized Upgrade with lock

This is the end of the introduction Java Object memory structure , Let's solve a new problem :

Why do I need to mark the state of the lock ? Does it mean synchronized There are many states of locks ?

stay JDK In previous releases ,synchronized Keyword implementation is directly based on the heavyweight lock . As long as we use it in our code synchronized,JVM Will apply to the operating system for lock resources ( Whether it's really a multithreaded environment or not ), Applying for a lock from the operating system is more resource intensive , It involves switching between user mode and kernel mode , In a word, it's rather troublesome , And the performance is not high .

JDK In order to solve JVM The problem of poor lock performance , Introduced ReentrantLock, It's based on CAS+AQS, It's like a spin lock . Spin means , When lock competition happens , Threads that have not won the lock will spin outside the door and wait for the lock to be released , Who steals and who executes .

 picture .png

The advantage of spin lock is , There is no need to switch to kernel mode and apply for the heavyweight lock of the operating system , stay JVM The layer can achieve spin waiting . But there is no panacea in the world ,CAS Spin avoids complex operations such as state switching , But it costs part of CPU resources , Especially when the predictable locking time is long and the concurrency is high , It will cause hundreds or thousands of threads to spin at the same time , Greatly increased CPU The burden of .

 picture .png

synchronized After all JDK My son , So probably in JDK1.6 Or earlier versions , The official response to synchronized Optimized , Put forward “ Lock escalation ” The concept of , hold synchronized The lock is divided into multiple states , That's what's mentioned in the picture above :

  • unlocked
  • Biased locking
  • Lightweight lock ( spinlocks )
  • Heavyweight lock

No lock is a Java The object is just new The state of coming out . When this object is first accessed by a thread , The thread will put its own thread id“ Paste to ” On its head (Mark Word Some of the middle digits have been modified ), Express “ you are mine ”:

 picture .png

There is no lock competition , So there's no blocking or waiting .

Why design “ Biased locking ” In this state ?

Let's recall , Are there really so many concurrent scenarios in a project ? No . Most of the time on most projects , A variable is executed by a single thread , At this point, it is obviously unnecessary to apply for a heavyweight lock directly from the operating system , Because there's no thread safety problem at all .

And in the event of lock contention ,synchronized It will be upgraded to lightweight lock under certain conditions , It can be understood as a spin lock , How many spins and when to give up spin ,JDK There is also a set of related control mechanisms , You can learn about .

It's also spin , therefore synchronized I will meet ReentrantLock The problem of : If the lock time is long and there are many spin threads , How to ?

It will be upgraded again , Become the traditional sense of heavyweight lock , Essentially, the operating system maintains a queue , Trade space for time , Avoid the cost of multiple threads spinning and waiting at the same time CPU performance , When the last thread ends, wake up the waiting thread to participate in a new round of lock competition .

Expanding reading ( It's not necessary ):

Thread safety ( in )-- Understand thoroughly synchronized( From biased lock to heavyweight lock )

screwing Synchronized Underlying implementation -- Biased locking

synchronized Case study

Let's take a look at a few cases , To deepen the synchronized The understanding of the .

  • In the same class synchronized method m1 and method m2 Are they mutually exclusive ?

 picture .png t1 Threads execute m1 Read the method this Object lock , however t2 Threads don't need to read locks , Each of the two is in its own way , There is no intersection ( Don't share a lock )

  • In the same class synchronized method m1 Can be called synchronized method m2 Do you ?

 picture .png synchronized It's a reentrant lock , It can be roughly understood that the same thread already holds the lock , You can get the lock again , And I will do it on a certain state quantity +1 operation (ReentrantLock It also supports reentry )

  • Subclass synchronization method synchronized method m You can call the synchronized method m Do you ?

 picture .png Before subclass objects are initialized , Will call the parent class construction method , In structure, it is equivalent to wrapping a parent class object , Using all of these this Lock object

  • Are static synchronous methods and non static synchronous methods mutually exclusive ?

 picture .png Let's play , Not the same lock , Not mutually exclusive

Redis The concept of distributed lock

talk about Redis Distributed lock , There are always questions like this or that :

  • What is distributed
  • What is distributed lock
  • Why do I need distributed locks
  • Redis How to implement distributed locks

front 3 Two questions can be answered together , as for Redis How to implement distributed locks , Let's put it next .

What is distributed ? It's a very complicated concept , It's hard for me to say exactly , So just draw a picture , Let's see each other :

 picture .png

One of the striking features of distributed computing is ,Service A and Service B Most likely not deployed on the same server , So they don't share the same piece JVM Memory . And it says , To achieve thread mutex , It must be ensured that all threads accessing are using the same lock (JVM Locks cannot guarantee mutual exclusion at this point ).

For distributed projects , As many servers as there are JVM Memory , Even if one is set in each piece of memory “ unique ” Lock of , On the whole, the locks in the project are not unique .

 picture .png

here , How to ensure that every JVM The threads on the shared lock ?

The answer is : Take out the lock , Let threads meet in the same piece of memory .

 picture .png

But locks can't exist out of thin air , The essence is still in memory , You can use Redis Cache as the host environment for locks , This is it. Redis The reason why distributed locks can be constructed .

Redis What does your lock look like

synchronized Key words and ReentrantLock, They are all locks that have been implemented , And there are signs and things like that . but Redis It's just a memory ... How to use it as a lock ?

One thing we need to be clear about ,Redis It can be used as distributed lock , Definitely not just because it's a piece of memory , otherwise JVM It also occupies memory , Why can't we implement distributed locks on our own ?

My personal understanding is , To customize a distributed lock , There must be at least a few conditions :

  • Multiple processes are visible ( A piece of memory independent of a multi node system )
  • Mutually exclusive ( It can be done through a single thread , It can also be done through an election mechanism )
  • Reentrant

Three points above Redis Can be satisfied . Under the above three conditions , Actually, how to design the lock , It all depends on how the individual defines the lock . It's like in real life , A lock is usually understood as having a keyhole 、 A small metal object that needs a key in . However, there is more than one form of lock , With the development of science and technology , What fingerprint lock 、 Iris locks come out one after another , But at the end of the day, they're called “ lock ”, Because it's guaranteed “ Mutually exclusive ”( I can , You can't ).

If we can design a logic , It can create a scene of “ Mutually exclusive events ”, Then it can be called “ lock ”. such as , A famous online store , Only one guest a day . There is no salesperson at the door , Just put a number machine , There is a ticket in it . If you go late , The tickets are gone , You can't get into this shop . In this scene , Customers without tickets can't get in , Locked out the door . here , The ticket machine caused “ Mutually exclusive events ”, So it can be called “ lock ”.

and Redis Provides setnx Instructions , If a key If it does not exist at present, it will be set successfully and return true, Otherwise, the settings will not be repeated , Go straight back to false. This is not the number machine of programming ? Of course , There's more than one command actually used , How to realize , Please read the next one ~

This one starts with JVM I'm talking about Redis Distributed lock , It also introduces Java Object memory structure and synchronized The underlying principle , I'm sure you're right “ lock ” I have my own perceptual knowledge . Next, we will introduce the case of distributed timing task Redis The usage scenarios of distributed lock .

I am a bravo1988, See you next time .



  1. ASP调用SDK微信分享好友、朋友圈
  2. ASP calls SDK wechat to share friends and circle of friends
  3. SpringCloud(六)Bus消息总线
  4. 详解JavaScript中的正则表达式
  5. Springcloud (6) bus message bus
  6. Explain regular expressions in JavaScript
  7. Java 响应式关系数据库连接了解一下
  8. Java14它真的来了, 真是尾气都吃不到了
  9. 视频:使用Docker搭建RabbitMQ环境
  10. Java responsive relational database connection
  11. Java14 it's really coming. I can't eat the exhaust
  12. Video: building rabbitmq environment with docker
  13. SpringCloud(六)Bus消息总线
  14. 详解JavaScript中的正则表达式
  15. Springcloud (6) bus message bus
  16. Explain regular expressions in JavaScript
  17. Docker实战:用docker-compose搭建Laravel开发环境
  18. Docker: building laravel development environment with docker compose
  19. 求助,JAVA如何获取系统当前所有进程
  20. 有人用过JMeter或用HttpUnit写过测试吗????
  21. Help, Java how to get all the current processes of the system
  22. Has anyone ever used JMeter or written tests in httpUnit????
  23. Living in a mountain village in late spring
  24. Partridge day, spring of HKUST
  25. JavaScript异步编程4——Promise错误处理
  26. 海康摄像SDK开发笔记(一):海康威视网络摄像头SDK介绍与模块功能
  27. JavaScript asynchronous programming 4 -- promise error handling
  28. Haikang video SDK development notes (1): introduction and module functions of Hikvision webcam SDK
  29. JOP:用于FPGA的嵌入式实时系统中的Java优化处理器内核
  30. Spring Boot源码:使用MongoDB MongoTemplate公开REST在几分钟内实现CRUD功能
  31. Spring Boot应用程序事件教程 - reflectoring
  32. 带有Resilience4j断路器的Spring云网关 - rome
  33. 经验分享:Apache Kafka的缺点与陷阱 - Emil Koutanov
  34. 通过Spring Boot Webflux实现Reactor Kafka
  35. 从Java 8升级到Java 11应该注意的问题
  36. Jop: Java optimized processor core for FPGA embedded real time system
  37. Spring boot source code: use mongodb mongotemplate to open rest to realize crud function in a few minutes
  38. Spring boot application event tutorial - reflecting
  39. Spring cloud gateway with resilience4j circuit breaker - ROM
  40. Experience sharing: shortcomings and pitfalls of Apache Kafka - Emil koutanov
  41. Realization of reactor Kafka through spring boot Webflux
  42. RPC框架设计----Socket与I/0模型
  43. Problems in upgrading from Java 8 to Java 11
  44. RPC framework design -- socket and I / 0 model
  45. RPC框架设计----I/0模型
  46. RPC framework design: I / 0 model
  47. RPC框架设计----NIO编程缓冲区Buffer
  48. RPC框架设计----NIO编程缓冲区Buffer
  49. RPC framework design -- NiO programming buffer
  50. RPC framework design -- NiO programming buffer
  51. Java多线程基础
  52. Java multithreading Foundation
  53. 码农飞升记-00-Java发展历程
  54. Development history of coder-00-java
  55. 码农飞升记-00-Java发展历程
  56. Development history of coder-00-java
  57. Spring and Autumn Moon
  58. Node.js与Spring Boot比较? - Ryan Gleason
  59. Spring WebFlux的明显陷阱 - ŁukaszKyć
  60. Spring创始人Rod大叔对YAML的真实想法