首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >需要多少解锁操作才能解锁Java中多次锁定的对象?

需要多少解锁操作才能解锁Java中多次锁定的对象?
EN

Stack Overflow用户
提问于 2018-07-31 14:02:58
回答 2查看 283关注 0票数 1

阅读java语言规范-内存模型我可以通过这条语句。

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

然后,我尝试使用下面的代码,但是它似乎不起作用。要么我不明白这句话要么我的代码没有做我想做的事..。

代码语言:javascript
复制
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次被释放,那么线程应该继续锁定锁?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-31 15:42:21

您的问题:“代码显示只需要一个锁操作,还是我遗漏了什么?”已经得到了“皮特·柯克姆”的回答。

主要问题的答案是“需要多少解锁操作才能解锁Java中多次锁定的对象?”就是你引用的那个。

下面的代码显示了Thread t1如何“多次锁定特定监视器”,以及“每次解锁都会逆转一次锁定操作的效果”。

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

代码语言:javascript
复制
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;
    }

}

产出如下:

代码语言:javascript
复制
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为我运行。

票数 1
EN

Stack Overflow用户

发布于 2018-07-31 14:43:19

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

代码语言:javascript
复制
    for (int i = 0; i < 10; i++) {
        synchronized (LOCK) { // lock gained on LOCK object
            //some code ...
        } // lock released on LOCK object
    }

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

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

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

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

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

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51615261

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档