2012-01-12 74 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