Location>code7788 >text

Remembering a Redisson online question → How can you release someone's lock?

Popularity:853 ℃/2024-07-22 08:57:33

Happy Moment

Today, another one of my best buddies got off and I'm left alone

I'm spilling my guts to a girl I like.

Me: I'll never find a girlfriend in my life

Her: How can that be, you are very good, there will be many girls who would like to be your girlfriend

I inwardly snickered and asked, So will you be my girlfriend?

Her: I am enlightening you, don't be gracious!

不要恩将仇报

Online issues

Sudden alarms in the production environment, alarm messages:

attempt to unlock lock, not locked by current thread by node id: b9df1975-5595-42eb-beae-bdc5d67bce49 thread-id: 52

Check the log to find the corresponding stack information

Exception in thread "thread0" : attempt to unlock lock, not locked by current thread by node id: b9df1975-5595-42eb-beae-bdc5d67bce49 thread-id: 52
	at $unlockAsync$4(:616)
	at $onComplete$0(:187)
	at .notifyListener0(:578)
	at (:552)
	at (:491)
	at (:184)
	at (:181)
	at (:607)
	at (:492)
	at (:41)
	at (:748)

Translated.

Attempt to release the lock from the current thread (node id: b9df1975-5595-42eb-beae-bdc5d67bce49 thread-id: 52)

That is: the current thread is attempting to release a lock on another thread.

How can I release someone else's lock?

指指点点

Basic Review

Before we troubleshoot the problem, let's figure out

node id: b9df1975-5595-42eb-beae-bdc5d67bce49 thread-id: 52

node id cap (a poem)thread-id what?

with respect tothread-idI'm sure we all understand that it's the id of the thread that threw the exception, right? That'snode id And?

I'll guide you with the eight-letter words.

Ask:redisson usableredis What data type is used to implement the lock in the

Answer:hash

Q: Thathash hit the nail on the headkeyfieldvalue What are the respective values of

Answer:key The value of is the lock name.field The value ofThread idvalue The value of is the number of reentries

Q: If multiple services go to acquire a lock at the same time, thefield It is not possible that the values of the locks are the same, e.g., the thread in which Service A acquires the lock has thethread-id is 52, and the thread in which Service B acquires the lock'sthread-id Also 52

At this point you are not a little panicked, but still tough answer: it is possible that the same

Q: So there's no problem, the thread for service A (thread-id=52) gets the lock and is performing business processing, the thread of service B (thread-id=52) can also get a lock, it's not a lock of loneliness?

A: Uh... Uh...

Obviously a detail was missed, and that isfieldIts value is notThread idRathernode id:thread-id, for example:b9df1975-5595-42eb-beae-bdc5d67bce49:52 And thisnode id just likeredisson (used form a nominal expression)Instance idThe following is an example of how to differentiate between the distributedredisson an actual example

Redisson Distributed Locking Implementation Source Code → Why Redisson Client is Recommended There's a very detailed description that's worth checking out for you guys

Releasing someone else's lock

talk is sheap show me the code

testLock

The code, I'm sure everyone can understand it, but I'll explain it anyway

  1. constructor's lock
  2. Attempt to acquire lock, wait time 1s, hold lock 3s
  3. If the lock is acquired, the business is processed; if it is not acquired, it is printed.Lock acquisition failed
  4. finally Guarantees that locks are released in both exception and non-exception cases

Isn't that normal, but it really doesn'tbug (question tag)

640 (15)

Let's adjust the code.

testLock_异常

(of a computer) runmultiThreadLockThe anomaly is coming.

异常信息

From the printout, we should be able to analyze what the problem is

  1. Thread 52 acquires the lock and executes in the business
  2. Thread 53 tries to acquire the lock, but the lock is held by thread 52
  3. Thread 53 Failed to acquire lock in 1s
  4. Thread 53, come in.finallyIf the lock is held, release the lock.
  5. redisson When releasing a lock, an exception is thrown if the thread holding the lock is not the current thread.

Thread 53, what's wrong with you, how can you release someone else's lock? You can't blame thread 53, we wrote the code, look at the commit logs, we have to pull this two arm out!!!!

哪个二臂写的

Forget it. Let's not pull it out. Let's get on with fixing it.

Problem fixing

Now that you've found the problem, fixing it is simple in several ways

Increase in waiting time

Increase the wait time for acquiring the lock, but this way can only reduce the exception, not completely fix the exception; because there will be multiple threads competing for the lock at the same time, it is not appropriate to set the wait time to any amount, unless it is set to no timeout, but setting it to no timeout may result in too many waiting threads, causing insufficient threads to use the situation. This is not recommended.

automatic release

get rid offinallyThis is equivalent to eliminating the source of the exception, so there will be no exceptions.

If you can't solve the problem, solve the person who raised it.

Do not actively release the lock, let the lock automatically due to release, because we set the lock holding time is 3s, 3s after the automatic expiration of the release. However, in actual business, we often set the lock holding time is relatively large (much larger than the average length of business execution), to ensure that the business will not be executed concurrently, if the business execution is completed without releasing the lock, it will lead to a long time the lock is invalidly occupied, and the subsequent thread to obtain the lock can only be waiting in vain. This method is not recommended

Record acquisition status

Look directly at the code and you'll understand

记录获取状态_1

What happens if the business takes longer than 3s to execute? Let's change the sleep time to 5s and execute the followingtestLock, you will find the same anomaly again!!!!

记录获取状态_异常

Let's analyze, the lock holding time is 3s, while the business execution time is 5s, that is to say, the lock has expired before the business has finished executing.redis It's automatically released, and when we release the lock after the business execution, the lock is gone, so how can we release it? Soredisson throws an exception; so when releasing the lock, you also need to add a condition

if (acquired && ())

acquired indicates whether the current thread has acquired the lock, while the() Indicates whether there are threads holding locks, if both aretrueIf you have a lock, then it is the current thread that holds the lock, and releasing it is no problem. It can be used, but it's not recommended because there are more elegant ways to handle it

judgemental holder

That's a much more elegant way of writing it.

判断持有者

It is straightforward to determine whether the lock is held by the current thread and release it if it is; you don't have to worry about whether the lock is held by another thread or whether it will be released automatically when it expires. Recommended method

summarize

  1. Sample code address:redisson-spring-boot-demo
  2. The purpose of locking is to ensure that the business of single-threaded execution, so the lock must be set to hold the length of time a little larger, otherwise the extreme case, the business is still in the execution of the lock but the expiration of the lock, contrary to the original purpose of locking!
  3. Locks must be actively released, must be actively released, must be actively released, not business related
  4. When releasing a lock, determine whether it is held by the current thread, it is not your lock, why do you release it?