首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Lock.tryLock()的用例

Lock.tryLock()的用例
EN

Stack Overflow用户
提问于 2017-01-22 06:40:52
回答 4查看 13.8K关注 0票数 9

API文档 of Lock接口的方法tryLock()中,这个代码示例被粘贴,

这种方法的一个典型用法是: 锁=.;如果(lock.tryLock()) { try { //操纵受保护的状态}最后{ lock.unlock();}{ //执行替代操作}

我的问题是,这个用例在Java 5之前是不存在的,还是以前通过其他一些技术实现的呢?

我无法理解执行、基于锁可用性的执行替代操作的必要性。

有人能解释一下这方面的实际用例吗?

我确信这种技术并不是直接替代synchronized编写无死锁代码的方法。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-01-24 14:28:00

一个直截了当的用例是线程处理一批元素,偶尔尝试提交已处理的元素。如果获取锁失败,则元素将在下一次成功尝试中提交,或在最终强制提交时提交。

在JRE本身中还可以找到另一个例子,ForkJoinTask.helpExpungeStaleExceptions()是一种用于执行任意线程可以执行的任务的方法,但一次只能执行一个线程,所以只有一个成功获取锁的线程才会执行它,所有其他线程都将返回,因为锁的不可用性意味着已经有一个线程正在执行该任务。

在Java 5之前实现类似的特性是可能的,如果您将内部锁定特性(它不支持可选)与可以表示为普通对象状态的锁定逻辑分离开来。这个答案提供了一个示例。

票数 3
EN

Stack Overflow用户

发布于 2017-01-25 00:02:59

我的问题是,这个用例在Java 5之前是不存在的,还是以前通过其他一些技术实现的呢?

Lock接口是在Java5中添加的,这就是您的意思吗?不知道之前有什么。

我无法理解执行基于锁可用性的替代操作的必要性。有人能解释一下这方面的实际用例吗?

好的。今天刚刚写了其中一篇。我的特定Lock实现是使用Jgroups协议栈在服务器集群之间共享的分布式锁。lock.tryLock(...)方法对集群进行RPC调用并等待响应。很有可能,多个节点可能试图锁定,它们的操作可能会发生冲突,导致延迟,当然还有一个锁会失败。这可以返回false或超时,在这种情况下,我的代码只是等待并再次尝试。我的代码是:

代码语言:javascript
复制
if (!clusterLock.tryLock(TRY_LOCK_TIME_MILLIS, TimeUnit.MILLISECONDS)) {
    logger.warn("Could not lock cluster lock {}", beanName);
    return;
}

另一个用例可能是这样一种情况,即代码的一个部分持有一个锁的时间很长,而代码的其他部分可能不希望等待那么长时间,而是希望完成其他工作。

这里是我的代码中使用tryLock(...)的另一个地方

代码语言:javascript
复制
// 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");
    }
}
票数 3
EN

Stack Overflow用户

发布于 2017-01-22 15:30:38

编写类似于该示例的代码的原因是,如果您有一个线程执行一个以上的任务。

想象一下你把它放在一个循环中:

代码语言:javascript
复制
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,或者更好地使用提交到线程池的对象。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41788074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档