2012-01-12 45 views
3

我想我只是沒有看到一些東西,因爲我已經得到了這個工作在過去。ReentrantLock.tryLock()沒有鎖定

我的鎖沒有持有獨佔鎖,並且當創建對象的新實例時,tryLock返回true,並且計劃另一個TimerTask

public class A { 
    private static Timer timer = new Timer(); 
    private static Lock clean_lock = new ReentrantLock(); 
    private static ConcurrentHashMap<String,B> _b_dict = new ConcurrentHashmap<String,B>(); 

    public A() { 
     if(clean_lock.tryLock()) { 
      timer.scheduleAtFixedRate(new TimerTaskThread(), new Date(), 60000); 
     } 
    } 

    //Various NON static methods 
    // use an iterator at one point so they must be NON static 

    class TimerTaskThread extends TimerTask { 
     public void run() { 
      //delete old stuff in _b_dict 
     } 
    } 
} 

//sample usage 
public class Main { 
    public Main() { 
     A a = new A(); 
     a.contains(new B()); 
    } 
} 
+0

爲什麼你需要一個鎖?爲什麼不在靜態塊中初始化靜態值?我看不到它會創建第二個任務。 – 2012-01-12 15:25:56

+1

它真的看起來像那樣嗎?你永遠不會用'clean_lock.unlock()'釋放鎖嗎? – 2012-01-12 15:26:15

+0

@JohnVint我相信這是它只能創造一個任務。 – 2012-01-12 15:27:21

回答

10

你創建從另一個線程其他A實例?因爲如果你是從同一個線程創建兩個實例,那麼鎖是可重入的,tryLock顯然返回true。

如果您確實想從構造函數而不是靜態塊進行計劃,則應使用靜態AtomicBoolean變量,並且只在compareAndSet(false, true)返回true時調度計時器。

+1

+1:斑點。 – 2012-01-12 15:28:27

+0

它是在同一個對象中創建的(稱之爲類C),並且C被多次實例化。 讓我跟蹤調試器中的C,認爲你可能釘牢它。 – Chris 2012-01-12 15:32:16

+0

@JB Nizet,那真是謝謝! – Chris 2012-01-12 15:37:16

3

爲了什麼目的,你在這裏使用鎖;只是爲了確保timer.scheduleAtFixedRate僅被調用一次(第一次調用A的構造函數)?

你可以做一個靜態初始化塊來代替,這樣就不需要鎖都:當類是

public class A { 
    private static final Timer timer = new Timer(); 
    private static final ConcurrentHashMap<String,B> _b_dict = new ConcurrentHashmap<String,B>(); 

    static { 
     timer.scheduleAtFixedRate(new TimerTaskThread(), new Date(), 60000); 
    } 

    // etc. 
} 

如果您使用靜態塊,調度將完成初始化(加載後),而不是第一次創建它的實例。

另一種可能性是使用AtomicBoolean

public class A { 
    private static final Timer timer = new Timer(); 
    private static final AtomicBoolean initDone = new AtomicBoolean(); 
    private static final ConcurrentHashMap<String,B> _b_dict = new ConcurrentHashmap<String,B>(); 

    public A() { 
     if (!initDone.getAndSet(true)) { 
      timer.scheduleAtFixedRate(new TimerTaskThread(), new Date(), 60000); 
     } 
    } 

    // etc. 
} 
1

這是我會寫它的方式。

public class A { 
    private static final ExecutorService service = Executors.newScheduledExecutorService(); 
    private static final ConcurrentMap<String,B> _b_dict = new ConcurrentHashmap<String,B>(); 
    static { 
     service.scheduleAtFixedRate(new Runnable() { 
      public void run() { 
       cleanUp(); 
      } 
     }, 1, 1, TimeUnit.MINUTES); 
    } 

    static void cleanUp() { 
     // remove old entries 
    } 
} 
+0

這就是即將改變它,但不幸的是JB發現鎖的真正問題。 – Chris 2012-01-12 15:38:13

+1

他發現它是件好事,但真正的答案是你不需要它。 – 2012-01-12 15:43:26