信号量用于暂停操作,不限制并发操作

时间:2015-07-08 17:01:50

标签: java multithreading concurrency semaphore

我有一个方法被许多线程不断调用,这些线程在数据结构中查找数据。

当需要更新该数据结构时,我需要阻止所有尝试查找的线程,直到更新完成。

我可以使用带有X许可证的信号量,并且让更新方法在执行更新之前获取所有X许可证然后再次释放它们 - 但是现在X也用于限制我的查找方法到X同时调用的次要目的,我不想要。

我还有哪些其他选项来阻止对update方法的调用而不限制同时执行它?

2 个答案:

答案 0 :(得分:4)

使用ReadWriteLock,特别是ReentrantReadWriteLock。每个读取线程都可以锁定readLock,当需要发生写入时,只需锁定writeLock

写锁定在保持时将阻止所有读取(和后续写入)发生,直到释放写锁定为止。持有readLock的线程可以同时执行。也就是说,许多线程可以同时保存readLock。

如果您使用的是Java 8,我建议使用StampedLock

答案 1 :(得分:0)

John Vint的答案 - 读者/作家锁 - 听起来最适合你的问题,但你让我想到了一个古老的,非常简单的设计模式,称为"旋转门"。

(警告!这是一个非答案:旋转栅门实际上并没有解决问题。它可能会阻止线程进入查找例程,但它对已经存在的线程没有任何作用当更新程序线程变为活动状态时,中查找例程。)

无论如何,十字转门可以追溯到信号量被认为是 低级基元的时间,从该基元可以导出所有其他同步对象。 (比Java更早的方式)。这可能是一种更有效的方法,但我一直都很喜欢这种实现的简单性:

class Turnstile {
    private final Semaphore semaphore = new Semaphore(1);

    // To be called in threads that need to "pass through" the turnstile.
    public void passThrough() {
        semaphore.acquire();
        semaphore.release();
    }

    // To be called only in the single thread that owns the turnstile.
    public void lock() {
        semaphore.acquire();
    }

    // To be called only in the single thread that owns the turnstile.
    public void unlock() {
        semaphore.release();
    }
}