当 ReentrantLock#tryLock(long,TimeUnit) 尝试获取锁时,它在做什么?

发布于 2024-12-20 00:34:25 字数 507 浏览 3 评论 0原文

当 ReentrantLock#tryLock(long,TimeUnit) 实现尝试获取锁时,它在做什么?假设线程A实际拥有myLock的锁,并且线程B调用myLock.tryLock(10,SECONDS),线程B是在睡眠还是在等待?

换句话说,这就是这 2 个实现的差异:

1.

while (true)
   try {
     if (readLock.tryLock())
       return;
     MILLISECONDS.sleep(5);
   }catch (InterruptedException e) {}

2.

 while (true)
   try {
     if (readLock.tryLock(5,MILLISECONDS))
       return;
   }catch (InterruptedException e) {}

What is the ReentrantLock#tryLock(long,TimeUnit) implementation doing when it tries to aquire a lock ? Assume Thread A acually owns the Lock of myLock, and Thread B call myLock.tryLock(10,SECONDS), is Thread B sleeping or waiting ?

In other words, was is the difference of this 2 implementations:

1.

while (true)
   try {
     if (readLock.tryLock())
       return;
     MILLISECONDS.sleep(5);
   }catch (InterruptedException e) {}

2.

 while (true)
   try {
     if (readLock.tryLock(5,MILLISECONDS))
       return;
   }catch (InterruptedException e) {}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

源来凯始玺欢你 2024-12-27 00:34:25

首先,如果锁被释放,第二个将等待不到 5 毫秒,因为它不需要等待从睡眠中唤醒。因此,它较少面临饥饿问题。

然后,jucl 包使用 LockSupport#park 方法来暂停线程,而不是 Thread.sleep。据我了解,它对线程调度程序有影响,park 允许较低的延迟,但不确定 sleep 是如何实现的。

另外,您的代码没有任何意义,通过 lock() 方法可以实现完全相同的效果。

First of all, the second will wait less than 5 millis if lock released, because it doesn't need wait for wake up from the sleep. So, it's less exposed to starvation problem.

Then, j.u.c.l package uses LockSupport#park methods to pause a thread, not Thread.sleep. And as I understand it makes difference on the thread scheduler, the park allows lower latency, but not sure how exactly the sleep is implemented.

Also, your code doesn't make any sense, exactly the same effect could be achieved by lock() method.

将军与妓 2024-12-27 00:34:25

它正在等待锁,并且线程处于睡眠状态。

在内部,如果 tryLock(long, TimeUnit) 方法无法立即获取锁,它会等待指定时间。如果锁在此时间之前变得可用,则它会立即返回该锁。请注意,在这种情况下,当有多个线程请求锁时,ReentrantLock 将随机选择一个线程将锁交给下一个线程。可以通过将 true 传递给构造函数 new ReentrantLock(true) 中的公平值来更改此行为。

第二个示例仅每五毫秒检查一次锁定。如果锁在休眠时变得可用,并在唤醒之前将其交给另一个线程,则该线程将无法获取锁。

如果您在许多线程等待锁的情况下使用此代码,请注意,您提供的两种解决方案都不能保证每个线程都会在某个时刻获得锁。在五毫秒结束之前,第二个代码可能会继续被另一个线程拦截。第一个代码是随机的,但即使设置了公平值,每个线程也会每五毫秒放弃其在队列中的位置。如果是这种情况,您最好增加超时值。一个好的值应该是每个线程轮流所需的最大时间的两倍左右。

It is waiting for the lock and the thread is asleep.

Internally, if the tryLock(long, TimeUnit) method fails to acquire the lock immediately, it waits for the amount of time specified. If the lock becomes available before this amount of time, it returns immediately with the lock. Note that in this case, when there are multiple threads requesting a lock, the ReentrantLock will randomly pick a thread to give the lock to next. This behavior can be changed by passing true to the fairness value in the constructor new ReentrantLock(true).

The second example will only check for the lock every five milliseconds. If the lock becomes available while it is sleeping and is given to another thread before it wakes up, this thread will be unavailable for acquiring the lock.

If you're using this code with many threads waiting for the lock, note that neither solution you have provided will guarantee that every thread will get the lock at some point. The second code can continue getting sniped by another thread just before the five milliseconds are up. The first code is random, but even with the fairness value set each thread will give up its place in line every five milliseconds. If this is the case you're better off increasing the timeout value. A good value would be about double the maximum amount of time that you would expect it to take for every thread to get a turn.

我偏爱纯白色 2024-12-27 00:34:25

从技术上讲,等待线程的状态没有区别。来自 JavaDoc:

如果锁被另一个线程持有,则当前线程将被禁用
用于线程调度目的并处于休眠状态[...]

这与睡眠情况下发生的情况非常相似,但我想我们不能肯定地说,除非我们知道实现。

现在,请注意这部分:

[...] 处于休眠状态,直到发生以下三种情况之一:
锁被当前线程获取;或[...]

这意味着如果锁同时空闲,它将获取它并返回。在另一种情况下,当它处于睡眠状态时,即使线程空闲,也没有机会获得锁。

两种情况之间可能出现的另一个细微差别是,定时 trylock 对 ReentrantLock 的公平策略很敏感。那是:

如果此锁已设置为使用公平排序策略,则可用锁
如果有其他线程正在等待该锁,则不会获取该锁。

众所周知,不定时的 trylock 是不公平的,即使其他线程已经在等待它,也可能会成功获取锁。

Technically there is no difference with respect to the state of the waiting thread. From the JavaDoc:

If the lock is held by another thread then the current thread becomes disabled
for thread scheduling purposes and lies dormant [...]

This is very similar to what happens in case of sleeping, but I guess we can't say for sure unless we know the implementation.

Now, note this part:

[...] lies dormant until one of three things happens:
The lock is acquired by the current thread; or [...]

That means that in case the lock becomes free in the meantime, it will acquire it and return. In the other case, while it is sleeping, the thread has no chance to get the lock even if it is free.

Another subtle difference that may appear between the two cases is the fact that the timed trylock is sensitive to the fairness policy of the ReentrantLock. That is:

If this lock has been set to use a fair ordering policy then an available lock
will not be acquired if any other threads are waiting for the lock.

The untimed trylock is known to be not fair and may succeed to acquire the lock even if other threads are already waiting on it.

无法言说的痛 2024-12-27 00:34:25

我猜第二个会等待 5 毫秒才能获得锁定,这与第一个会尝试立即锁定不同。因此线程 B 将等待,如果在 5 毫秒(5 毫秒内)锁内它没有获得锁,它将返回 false。通常,如果您的超时时间为 5 毫秒,则没有区别,但如果您增加此数字,您将获得清晰的图像。

5ms 是一个超时,它将等待 5ms 的锁,这意味着如果锁在 3ms 后可用,它将在 3ms 后返回 true。

I guess that the second one will wait for a 5 milliseconds to get a lock in difference with the first one which will try to lock immediately. So thread B will wait if in 5 ms (within 5ms) lock it doesn't get a lock it will return false. Normally there no difference if you have 5ms in your timeout but in case you increment this number you will get the clear image.

5ms is a timeout it will wait for 5ms for a lock that means if the lock is available after 3ms it will return after 3 ms with true.

寄居者 2024-12-27 00:34:25

有关如何实现锁和其他并发原语的重要参考,请参阅 Shavit 和 Herlihy 的优秀 The Art多处理器编程

For a great reference on how locks and other concurrency primitives are implemented see Shavit and Herlihy's excellent The Art of Multiprocessor Programming.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文