【问题标题】:Java thread lock when trying to lock/unlock with ReetrantLock(true)尝试使用 ReetrantLock(true) 锁定/解锁时的 Java 线程锁定
【发布时间】:2014-06-29 21:19:35
【问题描述】:

我在一个应用程序中使用ReetrantLock(true) 时遇到了一些问题,该应用程序检查两个图像之间的差异并根据百分比显示相似度。

出于某种原因,我的输入线程用于读取“相似”的最小百分比调用lock.lock(),并且该特定线程只是无限期地死锁,但我似乎无法弄清楚为什么只有那个线程死锁。

在下面的主要方法main(String[]) 中的SSCCE 中,内联Thread 用于从控制台获取输入,如果我在其中输入任何数字,它会正确存储它,但一旦它调用lock.lock(),它就会无限期地死锁我不确定为什么,因为 ReetrantLock 被告知要对调用者线程公平,并尝试在调用时对其进行排序。

private static volatile boolean running = false;

public static void main(String[] args)
{
    webcam2 webcam = new webcam2();
    webcam.start();
    (new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            Scanner scanner = new Scanner(System.in);
            while (running)
            {
                System.out.print("Enter Double: ");
                double val = scanner.nextDouble();
                lock.lock(); // locks indefinatly here
                if (val < 0.0D) reset = true;
                dif = val;
                System.out.println("Searching for value: " + dif);
                lock.unlock();
            }
            scanner.close();
        }
    })).start();
}

private static double dif = 0.0D;
private static boolean reset = false;
private static ReentrantLock lock = new ReentrantLock(true);

@Override
public void run()
{
    try
    {
        while (running)
        {
                // show image on window
                lock.lock();
                if (reset == true)
                {
                    reset = false;
                    lock.unlock();
                    doComplexStuffToImage();
                }
                lock.lock();
                doComplexStuffToImage();
                lock.unlock();
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

private static void doComplexStuffToImage()
{
    try
    {
        Thread.sleep(1000);
    }
    catch(InterruptedException ie)
    {
        //swallow exception
    }
}

public void start()
{
    new Thread(this).start();
    running = true;
}

public void stop()
{
    running = false;
}

【问题讨论】:

    标签: java multithreading locking deadlock


    【解决方案1】:

    一个线程正在锁定 ReentrantLock 而不是释放它。 “可重入”的意思是你可以多次调用 lock,但你必须调用 unlock() 相同的次数。您锁定两次,然后解锁一次,因此您实际上并没有解锁锁定,因此没有其他进程有机会。

    【讨论】:

    • 哦,现在我看到了我的愚蠢错误,输入线程只有在调用重置时才会运行,但只有在未锁定时才能调用。谢谢
    最近更新 更多