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 realize the Design of reentrant Lock by Redis

2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >

Share

Shulou(Shulou.com)05/31 Report--

This article mainly introduces Redis how to achieve the design of reentrant lock, the article is very detailed, has a certain reference value, interested friends must read it!

However, there are still some scenarios that are dissatisfied. For example, after the lock is acquired by the method, the lock may not be acquired when the method is adjusted internally. At this point, we need to improve the lock to a repeatable lock. Double lock refers to the thread as a unit, when the thread acquired the object lock, the thread can again acquire the lock on the object, the other thread is not allowed. The significance of repeatable locks is to prevent deadlocks. The principle of implementation is that each lock is associated with a request counter and a thread that owns it. When the count is 0, the lock is considered unoccupied; when the thread requests an unoccupied lock, JVM records the occupant of the lock and sets the request counter to 1. If the same thread requests the lock again, the count will be incremented; each time the thread exits the synchronization block, the counter value will be decremented. The lock is released until the counter is 0. About the overrides of the locks of the synchonized class and the other class: the duplicate class overrides the repeat method of the sink class, and then calls the repeat method in the sink class. If there is no duplicate lock, then this code will produce a deadlock.

Code demonstration

Non-repeatable

Non-repeatable lock

Use a non-reentrant lock

The current thread executes the call () method to get the lock first, then the inc () method executes the logic in inc (), and the lock must be released first. This example is a good illustration of the unrepeatable lock.

Reentrant lock

Lock implementation

Lock use

Repeatable means that the thread can enter the synchronous code block of the lock it already owns.

Design two thread call "call ()" method, the first thread call "call ()" method to obtain the lock, enter "lock ()" method, because the initial lockedBy is null, so it will not enter "while" to suspend the current thread, the thread is incremental lockedCount and record lockBy as the first thread.

Then the first thread enters the "inc ()" method, and because of the same process, it will not enter the "while" to suspend, and then increment lockedCount, when the first thread tries to lock, because of isLocked=true, he will not acquire the lock until the third thread calls unlock () twice to decrement lockCount to 0, then marks isLocked as false.

Design ideas

Suppose the key of the lock is "lock", hashKey is the id of the current thread: "threadId", and the lock automatic release time is assumed to be 20.

Acquire lock

Determine whether there is EXISTS lock in lock

If it does not exist, the lock is acquired by yourself, and the number of record reentry layers is 1.

Exists, indicating that someone has acquired the lock, and continue to determine whether it is your own lock, that is, to determine whether the current thread id exists as a hashKey: HEXISTS lock threadId

Does not exist, indicating that the lock already exists, and is not acquired by yourself, the lock acquisition failed.

Exists, indicating that the lock is acquired by yourself, the number of reentrants is + 1: HINCRBY lock threadId 1, and the automatic release time of the lock is last updated, EXPIRE lock 20

Release lock

Determine whether the current thread id exists as hashKey: HEXISTS lock threadId

Does not exist, indicating that the lock is invalid

Exists, which means the lock is still there. The number of reentrants minus 1: HINCRBY lock threadId-1

Get the new number of reentrants, and determine whether the number of reentrants is 0. If 0 means all locks are released, delete key: DEL lock

Therefore, the information stored in the lock must contain: key, thread identity, number of reentrants. You can no longer use a simple key-value structure, but the hash structure is recommended here. And to have all instructions operate in the same thread, use the lua script.

Lua script

Lock.lua

Local key = KEYS [1];-- the first parameter, the keylocal threadId of the lock = ARGV [1];-- the second parameter, the thread uniquely identifies local releaseTime = ARGV [2];-- the third parameter, the automatic release time of the lock if (redis.call ('exists', key) = = 0) then-- determines whether the lock already exists redis.call (' hset', key, threadId,'1') -- if it does not exist, acquire the lock redis.call ('expire', key, releaseTime);-- set the validity period return 1;-- return the result end;if (redis.call (' hexists', key, threadId) = = 1) then-- the lock already exists to determine whether the threadId is its own redis.call ('hincrby', key, threadId,' 1') -- if it is you, then the number of reentrants is + 1 redis.call ('expire', key, releaseTime);-- set the validity period return 1;-- return the result end;return 0;-- this indicates that you are not the one who acquired the lock and failed to acquire the lock.

Unlock.lua

-- keylocal key = KEYS [1] of the lock;-- unique ID of the thread local threadId = ARGV [1];-- determine whether the current lock is still held by it (redis.call ('hexists', key, threadId) = = 0) then--. If it is no longer its own, then directly return return nil;end;-- is its own lock, then the number of reentrants minus one local count = redis.call (' hincrby', key, threadId,-1). " -- determine whether the number of reentrants has been 0if (count = = 0) then-- equals 0, indicating that the lock can be released and redis.call ('del', key) can be deleted directly; return nil;end

Integrate in the project

Write RedisLock classes

@ Getter@Setterpublic class RedisLock {private RedisTemplate redisTemplate; private DefaultRedisScript lockScript; private DefaultRedisScript unlockScript; public RedisLock (RedisTemplate redisTemplate) {this.redisTemplate = redisTemplate; / / load the script to release the lock this.lockScript = new DefaultRedisScript (); this.lockScript.setScriptSource (new ResourceScriptSource (new ClassPathResource ("lock.lua")); this.lockScript.setResultType (Long.class) / / load the script that releases the lock this.unlockScript = new DefaultRedisScript (); this.unlockScript.setScriptSource (new ResourceScriptSource (new ClassPathResource ("unlock.lua") } / * * get lock * @ param lockName lock name * @ param releaseTime timeout (in seconds) * @ return key unlock identification * / public String tryLock (String lockName, long releaseTime) {/ / prefix of stored thread information to prevent conflicts with thread information in other JVM String key = UUID.randomUUID () .toString () / / execute script Long result = (Long) redisTemplate.execute (lockScript, Collections.singletonList (lockName), key + Thread.currentThread (). GetId (), releaseTime); / / judgment result if (result! = null & & result.intValue () = 1) {return key;} else {return null }} / * release lock * @ param lockName lock name * @ param key unlock identification * / public void unlock (String lockName, String key) {/ / execute script redisTemplate.execute (unlockScript, Collections.singletonList (lockName), key + Thread.currentThread () .getId (), null) }} these are all the contents of the article "how to implement the Design of reentrant Lock in Redis". Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!

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

Database

Wechat

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

12
Report