ReentrantLock始终通过同一线程锁定和解锁

时间:2019-03-14 13:05:10

标签: java multithreading reentrantlock

我试图在多线程上实现可重入锁,但由于某些原因,同一线程将解锁,然后再次锁定,从而导致始终使用同一线程来运行相同的操作。

下面是生成线程的代码

IntStream.range(0,(NUMBER_OF_THREADS)).forEach(index ->{
            boolean operation = (index % 2 == 0) ? true : false;
            Thread t = new Thread(new Client(operation,this));
            t.start();
});

这是线程的运行功能的工作原理

@Override
public void run() {
    while(!Thread.interrupted()) {
        System.out.println("Trying to acquire lock : " + main.getLock().tryLock()
                + " thread id " + Thread.currentThread().getName());
       // if (main.getLock().tryLock()) {
        try {
            main.getLock().lock();
            if(main.getLock().isHeldByCurrentThread()) {
                System.out.println("Lock held by this thread " + main.getLock().isHeldByCurrentThread()
                        + " thread id : " + Thread.currentThread().getName());
                if (operation) {
                    main.getcAaccount().deposit(1);
                } else {
                    main.getcAaccount().withdraw(2);
                }
                Thread.currentThread().sleep(3000);
            }
        } catch (InterruptedException e) {
                e.printStackTrace();
        } finally {
            System.out.println("Thread id : " + Thread.currentThread().getName() + " unlocking");
            main.getLock().unlock();//always have the unlock part here to ensure it unlock
        }
}

它正确地打印出其他5个线程正试图获取该锁并失败,然后线程id ...正在解锁...并且即使该线程应该正在睡眠,该线程也立即再次锁定。

在这种逻辑情况下我错过了任何东西吗?

先谢谢您。

EDIT建议的修复程序的屏幕快照。 Still, same thread id unlocks and locks immediately

1 个答案:

答案 0 :(得分:2)

重新进入要求每个锁定之后都有随后的解锁。例如,如果我调用lock.lock()三次,则期望我也调用lock.unlock()三次。在发生此事件序列之前,ReentrantLock不会认为自己已解锁。

您没有意识到lock.tryLock(),如果成功的话,本质上就像调用lock.lock()。因此,通过lock两次,您还需要两次unlock。在您的代码示例中,您只能解锁一次,因此最初锁定的线程在技术上仍拥有该锁。

修复起来应该很简单,您可以从代码中删除第二个lock.lock(),并且相互排斥仍然有效。要么,或者如果您需要锁定锁定,则将lock.tryLock()替换为lock.lock()

根据您的编辑 ,您已解决了删除多余锁的问题,但现在您遇到了计时问题。您实际上并不需要tryLock。您可以用lock替换它,因为lock的调用将挂起线程并阻塞(如果已经持有了锁(最终在调用解锁时唤醒))。

相关问题