2

Go: Story of TryLock Function

 1 year ago
source link: https://medium.com/a-journey-with-go/go-story-of-trylock-function-a69ef6dbb410
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Go: Story of TryLock Function

1*aMcuI9iWGwVWobLFlxfauQ.png

Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.

ℹ️ This article is based on Go 1.18.

Go 1.18 comes with a new function TryLock (for the mutexes sync.Mutex and sync.RWMutex) that allows the developer to try acquiring a lock in a non-blocking mode, i.e. if the lock is already acquired, the function will simply return the boolean false rather than waiting for the lock to be released.

This function piqued my curiosity because, although its name is explicit, its use cases are not obvious. Let’s collect information about it to better understand its usage.

Workflow

To better understand the workflow of a mutex, I suggest you read my article “Go: Mutex and Starvation.”

The lock of a mutex is not available if:

  • the lock is currently held by another goroutine.
  • the lock is not held but the mutex is in starvation mode; i.e., the lock will be handed off to the next waiter.

In either of these cases, the function TryLock will immediately return false. Here is a diagram that summarizes those two use cases:

1*qN5pMbbpjKw97veR6cAnww.png

TryLock function will return false.

This is a rather fast operation since it only relies on a single-bit operation.

If the lock is available, the goroutine will try to acquire it the same way it does for the Lock function and return the result of this operation. In case it is not available, the goroutine is not going to spin or be parked; it is a full non-blocking mode.

What Issue Does it Solve?

The documentation clearly states the cases to use this function will be rare:

Note that while correct uses of TryLock do exist, they are rare, and use of TryLock is often a sign of a deeper problem in a particular use of mutexes.

Indeed, for many years (sees this discussion in 2012, this issue in 2013, or this other discussion in 2013), this feature did not appear to be needed or even to solve any real issue, and none of the discussions previously mentioned brought any real use case. So what could this implementation could bring to the community? Actually, many packages tried to implement a TryLock function but none of them can properly be integrated with the race detector. At least, with official support, it becomes easier to take profit from the race detector natively.

Go Standard Library and Other Languages

The Go source code does not use this new function internally. However, Go used to have a similar function in the runtime in Go1.6. This was used to acquire a lock during the profiling to scan the stack. In case the runtime was not able to acquire the lock, the trace was simply skipped.

Other programming languages — Java, Objective-C, Zig, and many others — implement the same function. Fortunately, an old version of the JRE was implementing this function giving us another real use case: the lock was protecting a function responsible for purging a queue. Since the queue can be purged by any thread and does not need to be purged multiple times, the first to acquire the lock would perform the task while the other threads can just resume their work.

If you have ever used this function or know another use case in Go or another language, I will be happy to hear about it in the comments.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK