如何在while循环中安全地使用信号量?

时间:2014-05-15 22:19:19

标签: java synchronization semaphore try-finally

在下面的代码片段中,我使用信号量来同步对某些资源的访问。

public void m () {
    permit.acquire ();
    while (!canFoo ()) {
        permit.release ();
        reticulateSpines ();
        permit.acquire ();
    }
    doFoo ();
    permit.release ();
}

在try / finally中包含获取/释放周期可能是合理的。考虑到while循环的存在,我怎么能这样做呢?

1 个答案:

答案 0 :(得分:2)

根据每个acquire 必须的原则,我建议:

private final Semaphore permit = new Semaphore(8, true);
private final Random random = new Random();

private boolean canFoo() {
    return random.nextBoolean();
}

private void doFoo() {
    System.out.println("Foo done!");
}

private void reticulateSpines() {
    System.out.println("Spines reticulated!");
}

public void m() throws InterruptedException {
    permit.acquire();
    try {
        while (!canFoo()) {
            permit.release();
            try {
                reticulateSpines ();
            } finally {
                permit.acquire();
            }
        }
        doFoo();
    } finally {
        permit.release();
    }
}

但是 - 我不确定您是否正在使用信号量。看起来更像是在寻找像ReentrantLock这样可以消除自旋锁循环的东西。

ReadWriteLock fooLock = new ReentrantReadWriteLock();
Lock fooReadLock = fooLock.readLock();
Lock fooWriteLock = fooLock.writeLock();

public void n() throws InterruptedException {
    fooWriteLock.lock();
    try {
        doFoo();
    } finally {
        fooWriteLock.unlock();
    }
}

甚至可能

public void o() throws InterruptedException {
    while (!fooWriteLock.tryLock()) {
        reticulateSpines();
    }
    try {
        doFoo();
    } finally {
        fooWriteLock.unlock();
    }
}