多个方法之间的java同步

lch*_*lch -1 java concurrency multithreading synchronization

class xyz {

    private Object lock = new Object();

    // value will come from database
    private boolean deleteOncePerDay; 

    private void clearAll() {
        synchronized (lock) {
            if(!deleteOncePerDay) {
                database.deleteNames();
                database.deleteAddresses();
                database.deletePhoneNums();

                // set database value to true
                deleteOncePerDay = true;
            }
        }   
    }

    @Scheduled(fixedDelay = 50000)
    public void fetchNames() {
        clearAll();
        synchronized (lock) {
            database.saveNames();
        }
    }

    @Scheduled(fixedDelay = 50000)
    public void fetchAddresses() {
        clearAll();
        synchronized (lock) {
            database.saveAddresses();
        }
    }

    @Scheduled(fixedDelay = 50000)
    public void fetchPhoneNums() {
        clearAll();
        synchronized (lock) {
            database.savePhoneNums();
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

3 个 fetch 方法在不同的线程中工作,每个 fetch 方法需要不同的时间来保存它们的数据。

我的目标:

  1. 当一个线程正在删除(ClearAll)数据时,其他线程不应同时保存数据。

  2. 当一个线程正在保存数据时,不应有其他线程正在删除数据。

  3. 当没有线程在 clearAll() 上工作时,所有线程可以同时保存数据。

有了上面我想我实现了 1 & 2。但是我错过了 3。由于每个 fetch 方法都被同步块包围,因此只有 fetch 方法会在时间锁定,因此不满足条件 3。

有人能帮我吗?

Ime*_*gha 5

在这种情况下,您可以在 java 中使用ReadWriteLock。而不是synchronized(lock){}块,使用如下。

// Initialization
ReadWriteLock lock=new ReentrantReadWriteLock();
Run Code Online (Sandbox Code Playgroud)

clearAll()方法中。

lock.writeLock().lock();
try{
    // Do your stuff here
} finally{
    lock.writeLock().unlock();
}
Run Code Online (Sandbox Code Playgroud)

在所有其他方法中,只需获得一个读锁并做你的事情。

lock.readLock().lock();
try{
    // Do your stuff here
} finally{
    lock.readLock().unlock();
}
Run Code Online (Sandbox Code Playgroud)

ReadWriteLock 允许任意数量的线程获得读锁,但要获得写锁,必须释放所有读锁。此外,在获取写锁定时不会发生读取。

另外,我认为您应该查看可以在数据库级别实现所有这些的数据库事务