使用Java排队锁

时间:2016-11-06 21:01:03

标签: java multithreading locking

我正在寻找关于如何使用Java中的锁使这个代码成为线程安全的建议。我知道有很多带锁的陷阱;可能出现的模糊问题,竞争条件等。以下是我想要实现的基本思路,实施起来相当天真:

public class MultipleThreadWriter {

boolean isUpgrading=false;
boolean isWriting=false;


public void writeData(String uniqueId) {

    if (isUpgrading) 
        //block until isUpgrading is false

    isWriting = true;
    {   
        //do write stuff    
    }
    isWriting = false;

}

public void upgradeSystem() {

    if (isWriting)
        //block until isWriting is false

    isUpgrading = true;
    {
        //do updates
    }
    isUpgrading = false;

}

}

基本思想是允许多个线程同时写入数据。没关系,因为没有两个线程会写入属于同一uniqueId的数据。但是,“系统升级”操纵所有uniqueIds的数据,因此它必须阻塞(排队等待)直到没有数据被写入才能启动,此时它会阻止所有写入,直到完成为止。 (绝对不是消费者/生产者模式在这里进行 - 升级是随意进行的,即与正在写入的数据无关。)

2 个答案:

答案 0 :(得分:2)

这听起来像readers-writer lock的好应用。

然而,在这种情况下,您的读者"是可以同时运行的小型更新任务,以及您的" writer"是系统升级任务。

Java标准库中有一个实现:

java.util.concurrent.locks.ReentrantReadWriteLock

锁具有合理非公平模式。如果您希望系统升级在计划后尽快运行,请使用锁的 fair 模式。如果您希望在空闲时间应用升级(即等到没有小的更新),那么您可以使用非公平模式。

由于这是读者 - 作者锁定的一种非正统应用(你的读者实际上也在写作!),请务必在代码中对此进行评论。您甚至可以考虑围绕提供ReentrantReadWriteLock vs localUpdateLock方法的globalUpdateLock类编写包装器,这些方法分别委托给readLockwriteLock

答案 1 :(得分:0)

根据@DaoWen的回答,这是我未经测试的解决方案。

public class MultipleThreadWriter {

private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();


public void writeData() {

    r.lock();
    try {   
        //do write stuff    
    } finally {
        r.unlock();
    }

}

public void upgradeSystem() {

    w.lock();
    try {
        //do updates
    } finally {
        w.unlock();
    }

}
}