首页 > 解决方案 > 等待一个锁解锁,解锁后不加锁

问题描述

对不起,如果标题是绕口令,但我不能说得更好,因为这正是我想做的。

我有这个方法/代码:

// No need fairness (false) the first to get it is good to go
private final Lock TEST = new ReentrantLock(false)

public methodCalledByMultipleThreads() {

    // 1st code section - no concurrency problems
    // regardless of what happen in section 2 a thread that just called
    // this function should always be able to run section 1

    // 2nd code section begin

    if (rare_condition && TEST.tryLocking()) {
        // check again to avoid limit cases where "rare_condition" value
        // is invalidated by another thread (who ran "important stuffs")
        // and just released/unlock TEST with "TEST.unlock();"
        if (check_rare_condition_again) {
            // ##### do "important stuffs" ##### 
            // release lock
            TEST.unlock();
        }
    }

    TEST.waitUntilUnlocked(); // this is what I actually would like to do
    // ##### do other stuffs ##### 

}

当然,“waitUntilUnlocked”不应该在等待结束时锁定“TEST”。我试图通过使用信号量来获得想要的行为......这真的很糟糕,信号量不是为此而制作的,并且在这种情况下也会导致开销(内部许可计数不计算任何东西......只是一个花哨的锁):

private final Lock TEST = new ReentrantLock(false)

// absurd high value (Integer.MAX_VALUE) for permits, to allow "virtually"
// infinite threads to works with this code
private final Semaphore SEM = new Semaphore(Integer.MAX_VALUE, true);

public methodCalledByMultipleThreads() {

    // 1st code section

    // 2nd code section begin

    if (rare_condition && TEST.tryLocking()) {
        if (check_rare_condition_again) {

            // waits to gets all permits
            SEM.acquireUninterruptibly(Integer.MAX_VALUE);

            // ##### do important stuffs ##### 

            // release all permits
            SEM.release(Integer.MAX_VALUE);
            // release lock
            TEST.unlock();
        }
    }
    // ask one permit
    SEM.acquireUninterruptibly();
    //  ##### do other stuffs ##### 
    // release one permit
    SEM.release();

}

上面的解决方案是“有效的”(幸运的是,在实际实现中,代码足够慢,不会导致任何边缘情况......现在)但理论上是错误的,因为“SEM.release(Integer.MAX_VALUE);” 和“TEST.unlock();” 应该是一回事。

如果没有这个丑陋的黑客,我怎么能得到这种行为?

标签: javaperformanceconcurrencylocking

解决方案


推荐阅读