在API文档 of Lock接口的方法tryLock()中,这个代码示例被粘贴,
这种方法的一个典型用法是: 锁=.;如果(lock.tryLock()) { try { //操纵受保护的状态}最后{ lock.unlock();}{ //执行替代操作}
我的问题是,这个用例在Java 5之前是不存在的,还是以前通过其他一些技术实现的呢?
我无法理解执行、基于锁可用性的执行替代操作的必要性。
有人能解释一下这方面的实际用例吗?
我确信这种技术并不是直接替代synchronized编写无死锁代码的方法。
发布于 2017-01-24 14:28:00
一个直截了当的用例是线程处理一批元素,偶尔尝试提交已处理的元素。如果获取锁失败,则元素将在下一次成功尝试中提交,或在最终强制提交时提交。
在JRE本身中还可以找到另一个例子,ForkJoinTask.helpExpungeStaleExceptions()是一种用于执行任意线程可以执行的任务的方法,但一次只能执行一个线程,所以只有一个成功获取锁的线程才会执行它,所有其他线程都将返回,因为锁的不可用性意味着已经有一个线程正在执行该任务。
在Java 5之前实现类似的特性是可能的,如果您将内部锁定特性(它不支持可选)与可以表示为普通对象状态的锁定逻辑分离开来。这个答案提供了一个示例。
发布于 2017-01-25 00:02:59
我的问题是,这个用例在Java 5之前是不存在的,还是以前通过其他一些技术实现的呢?
Lock接口是在Java5中添加的,这就是您的意思吗?不知道之前有什么。
我无法理解执行基于锁可用性的替代操作的必要性。有人能解释一下这方面的实际用例吗?
好的。今天刚刚写了其中一篇。我的特定Lock实现是使用Jgroups协议栈在服务器集群之间共享的分布式锁。lock.tryLock(...)方法对集群进行RPC调用并等待响应。很有可能,多个节点可能试图锁定,它们的操作可能会发生冲突,导致延迟,当然还有一个锁会失败。这可以返回false或超时,在这种情况下,我的代码只是等待并再次尝试。我的代码是:
if (!clusterLock.tryLock(TRY_LOCK_TIME_MILLIS, TimeUnit.MILLISECONDS)) {
logger.warn("Could not lock cluster lock {}", beanName);
return;
}另一个用例可能是这样一种情况,即代码的一个部分持有一个锁的时间很长,而代码的其他部分可能不希望等待那么长时间,而是希望完成其他工作。
这里是我的代码中使用tryLock(...)的另一个地方
// need to wait for the lock but log
boolean locked = false;
for (int i = 0; i < TRY_LOCK_MAX_TIMES; i++) {
if (lock2.tryLock(100, TimeUnit.MILLISECONDS)) {
logger.debug("Lock worked");
locked = true;
break;
} else {
logger.debug("Lock didn't work");
}
}发布于 2017-01-22 15:30:38
编写类似于该示例的代码的原因是,如果您有一个线程执行一个以上的任务。
想象一下你把它放在一个循环中:
while (true) {
if (taskA_needsAttention() && taskA_lock.tryLock()) {
try {
...do some work on task A...
} finally {
taskA_lock.unlock();
}
} else if (taskB_needsAttention() && taskB_lock.tryLock()) {
try {
...do some work on task B...
} finally {
taskB_lock.unlock();
}
} else ...
}就我个人而言,我不想写那样的代码。我更愿意让不同的线程负责任务A和任务B,或者更好地使用提交到线程池的对象。
https://stackoverflow.com/questions/41788074
复制相似问题