2017-03-16 141 views
-1
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(); 
     } 
    } 

} 

3種提取方法在不同的線程中工作,每種提取方法在不同的時間保存他們的數據。多種方法之間的java同步

我的目標:

  1. 當一個線程被刪除(ClearAll)數據,沒有其他線程同時應保存數據。

  2. 當線程正在保存數據時,其他線程不應該刪除數據。

  3. 當沒有線程在clearAll()上工作時,所有線程都可以同時保存數據。

利用上述我想我實現1 & 2.但是我錯過3.因爲每次提取方法由同步塊包圍,僅提取方法將在時間獲得鎖,所以不滿足條件3。

有人可以幫助我嗎?

回答

4

在這種情況下,您可以在java中使用ReadWriteLock。如下所示,而不是synchronized(lock){}塊。

// Initialization 
ReadWriteLock lock=new ReentrantReadWriteLock(); 

clearAll()方法中。

lock.writeLock().lock(); 
try{ 
    // Do your stuff here 
} finally{ 
    lock.writeLock().unlock(); 
} 

在所有其他方法中,只需讀取鎖定並執行操作即可。

lock.readLock().lock(); 
try{ 
    // Do your stuff here 
} finally{ 
    lock.readLock().unlock(); 
} 

一個ReadWriteLock中允許任何數目的線程來獲取讀鎖,但要獲取寫鎖,所有的讀鎖都被釋放。此外,在進行寫入鎖定時不會發生讀取。

此外,我認爲你應該看看數據庫事務,你可以在數據庫級別實現所有這些。

+0

使用Lock界面中概述的慣用法通常是一個很好的習慣:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html。如果lock()拋出一個異常(它可以!),調用try塊內部的鎖定將導致IllegalMonitorStateException,因爲即使當前線程不是所有者,finally中的清除仍然會嘗試解鎖()的鎖。 –

+0

我明白了。感謝評論@JohnH –

-1
@Scheduled(fixedDelay = 50000) 
    public void whatever() { 
     clearWhatever(); // no one passed barrier, no saves happening 
     CyclicBarrier(); 
     database.saveWhatever(); // all passed barrier, no clears happening. 

    } 

根據你的1,2,3情況,這應該把工作劃分清楚,並且不存在併發問題。