要解锁在Java中多次锁定的对象,需要执行多少次解锁操作?

时间:2018-07-31 14:02:59

标签: java multithreading

阅读Java语言规范-内存模型我在此声明中提到了。

  

线程t可以多次锁定特定的监视器;每个解锁   反转一次锁定操作的效果。

然后,我使用下面的代码尝试了此操作,但是它似乎不起作用。 要么我不理解该语句,要么我的代码没有按照我想要的去做……

public class MultipleLocks {


private static final Object LOCK = new Object();

public static void main(String[] args) throws InterruptedException {

    Thread t1 = new Thread(() -> {
        for (int i = 0; i < 10; i++) {
            synchronized (LOCK) {
                //some code ...
            }
        }


        synchronized (LOCK) {
            try {
                LOCK.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });

    t1.start();

    Thread t2 = new Thread(() -> {

        synchronized (LOCK) {
            System.out.println("I can acquire a lock !");
        }
    });

    t2.start();

    synchronized (LOCK) {
        LOCK.notify();
    }

    }


}

11-锁 仅解锁一次?

代码显示只需要一个锁定操作,否则我遗漏了什么?

编辑:

如果我的代码是错误的,我该如何模拟n次获取锁并将其释放n次,如果n-1次释放,则线程应继续锁定该锁?

2 个答案:

答案 0 :(得分:2)

此代码对对象的状态没有任何作用:

x

该锁在同步块的开始处获得,并在结束时释放。这样做十次,使对象保持与循环开始时相同的状态。

然后,Thread1获取锁,然后等待,这导致它释放锁,直到另一个线程通知该对象。

  

线程释放该监视器的所有权,并等待直到另一个   线程通知在此对象的监视器上等待唤醒的线程   Object.wait() javadocs

Thread2获取一个锁,打印程序的唯一输出,然后释放该锁。

主线程获取一个锁,通知一个正在等待的线程,然后释放该锁。

因此,线程可以按几种顺序获取锁,所有这些都导致相同的输出。

答案 1 :(得分:1)

您的问题“ 代码显示仅需要执行一次锁定操作,或者我缺少某些内容?”已由@Pete Kirkham回答。

您引用的主要问题“ 要对用Java多次锁定的对象进行解锁需要多少次解锁操作?”的答案。

以下代码显示了Thread t1多次锁定一个特定的显示器”和“ 每次解锁会反转一次锁定操作的效果”的方式。< / p>

Thread t1进入synchronize块三次。每当输入synchronize块时,都需要一个(附加)锁。每次留下synchronize块时,都会释放一个锁。因此,t1离开后,所有synchronizeThread t2首先可以进入synchronize块。

public class Locking {

    private static Object o = new Object();

    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(Locking::lockSeveralTimes);
        Thread t2 = new Thread(Locking::lockOnce);
        t1.start();
        Thread.sleep(100); // give t1 some time to start
        t2.start();
    }

    protected static void lockOnce() {
        synchronized (o) {
            System.out.println("DONE");
        }
    }

    protected static void lockSeveralTimes() {
        try {
            System.out.println("Has Lock: " + Thread.holdsLock(o));
            synchronized (o) {
                System.out.println("Aquired Lock: " + Thread.holdsLock(o) + " / Times: " + getLockedMonitorsCount());
                waitOneSecond();
                synchronized (o) {
                    System.out.println("Aquired Lock: " + Thread.holdsLock(o) + " / Times: " + getLockedMonitorsCount());
                    waitOneSecond();
                    synchronized (o) {
                        System.out.println("Aquired Lock: " + Thread.holdsLock(o) + " / Times: " + getLockedMonitorsCount());
                        waitOneSecond();
                        System.out.println("Going to release lock. Still holds: " + Thread.holdsLock(o) + " / Times: " + getLockedMonitorsCount());
                    }
                    waitOneSecond();
                    System.out.println("Going to release lock. Still holds: " + Thread.holdsLock(o) + " / Times: " + getLockedMonitorsCount());
                }
                waitOneSecond();
                System.out.println("Going to release lock. Still holds: " + Thread.holdsLock(o) + " / Times: " + getLockedMonitorsCount());
            }
            System.out.println("Still holds: " + Thread.holdsLock(o));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected static void waitOneSecond() throws InterruptedException {
        Thread.sleep(1000);
    }

    protected static int getLockedMonitorsCount() {
        return ManagementFactory.getThreadMXBean().getThreadInfo(new long[] { Thread.currentThread().getId() }, true, false)[0].getLockedMonitors().length;
    }

}

输出为:

Has Lock: false
Aquired Lock: true / Times: 1
Aquired Lock: true / Times: 2
Aquired Lock: true / Times: 3
Going to release lock. Still holds: true / Times: 3
Going to release lock. Still holds: true / Times: 2
Going to release lock. Still holds: true / Times: 1
Still holds: false
DONE

使用JDK 8为我运行。