当前位置: 首页 > 面试题库 >

每当我更改同步关键字的位置时,wait(n)的行为就不同

虞承泽
2023-03-14
问题内容

参考下面的代码

     public void acquire(){
        synchronized(a){
            print("acquire()");
            try{
                //Thread.sleep(5000);
                synchronized(this){
                    wait(5000);
                }
                print("I have awoken");
                print("" + a);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        print("Leaving acquire()");
    }


    public void modify(int n){
        print("Entered in modfy");
        synchronized(a){
            try{
                //Thread.sleep(5000);
                synchronized(this){
                    wait(5000);
                }
                this.a=n;
                print("new value" + a);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }

        final SynchoTest ttObj = new SynchoTest();
        Thread A = new Thread(new Runnable(){
            public void run() {
                ttObj.acquire();    
            }
        },"A");

        Thread B = new Thread(new Runnable(){
            public void run() {
                ttObj.modify(97);   
            }
        },"B");
        A.start();
        B.start();

据我所知,wait(n)会暂停线程,直到调用notify()/ notifyAll()或指定的时间n结束为止。

但…

  • 在上面的方法中,如果我像使用Thread.sleep(n)一样直接使用wait(n),则会得到运行时异常。
  • 如果我同步这两个方法,而不是将wait(n)包含在同步块中,那么我没有收到任何异常,但是两个线程都将永远被阻塞。
  • 但是,如果我确实喜欢在同步块周围附加即wait(n),则它工作正常。

请告诉我为什么?还告诉我,如果我使用sleep(n)而不是wait(n),为什么在定位同步块上没有什么不同?

我的问题是关于关键字的各个位置上的wait(n)的各种结果。

@灰色

notify()或notifyAll()和wait()必须在您正在等待的对象的同步块中

向我解释了为什么我通过将同步块放置在各个位置来获取运行时异常。

现在请解释一下为什么

public void method(){
    synchronized(a){
        synchronized(this){
            wait(n);
        }
    }
}

工作正常。但

public synchronized void method(){
    synchronized(a){
        wait(n);
    }
}

永远阻塞我的线程。


问题答案:

与定位同步关键字无关。由于您锁定了另一个对象并尝试等待另一个对象,因此您面临问题。好吧,@ Gray已经对此进行了解释,因此不再重复。

对于您的另一个问题,关于为什么两个线程都被阻塞;

线程A:锁定此[A:可运行]

线程A:锁定[A:可运行]

线程B:正在等待[A:可运行,B:已阻止]

线程A:释放该线程(表示等待)[A:定时等待,B:已阻止]

线程B:锁定此线程[A:定时等待,B:可运行]

线程B:等待已被线程A锁定的线程[A:定时等待,B:已阻止]

线程A:等待被线程B锁定的线程[A:已阻止,B:已阻止]



 类似资料:
  • 当我滚动时,我正在使用。当您滚动到底部时,它将更新数据。更新数据后。返回顶部。理想情况下,我希望保留中的职位。我该怎么做呢? InnerClass

  • 本文向大家介绍Java中的同步关键字,包括了Java中的同步关键字的使用技巧和注意事项,需要的朋友参考一下 当我们在程序中启动两个或多个线程时,可能会出现多个线程尝试访问同一资源,最终由于并发问题,它们可能产生无法预料的结果的情况。例如,如果多个线程试图在同一文件中写入数据,则它们可能会破坏数据,因为其中一个线程可以覆盖数据,或者一个线程同时打开同一文件时,另一个线程可能正在关闭同一文件。 因此,

  • 问题内容: 我有一个可编辑单元格。当我单击一个单元格时,它将进入编辑模式;当我使用方向箭头在单元格中移动时,也会发生同样的情况。现在,我想选择单元格而不是开始编辑,并且仅在按下键时才编辑单元格。 如果需要任何其他信息,请索取。 编辑:键的动作 现在这是用于左箭头动作,不难从这一个推论出其余三个: 这是您绑定此操作的方式: 哦,我差点忘了,要选择单元格而不是在“鼠标单击”上进行编辑: 将必须添加到表

  • 问题内容: 考虑以下代码: 为什么会这样呢? 为确保以上内容正确无误,我刚刚在Windows上的Python 2.5.4、2.6.5、2.7b2,Python 3.1和Linux上的Python 2.7b1上进行了测试。 看起来所有这些对象之间都具有一致性,所以这是设计使然。我想念什么吗? 我只是从我的一些个人域过滤脚本中发现失败了。 问题答案: 验证对象的身份,和Python,任何执行时,它符合

  • 问题内容: 我想将不同的字体行添加到JTextArea,但是最后一种字体似乎会覆盖其他字体。 请帮忙… 问题答案: 尝试使用JEditorPane / JTextPane http://download.oracle.com/javase/tutorial/uiswing/components/editorpane.html 这些支持HTML格式。普通的JTextArea的setFont方法将为整

  • 问题内容: c#是否具有自己的java“ synchronized”关键字版本? 即在Java中,可以将其指定为函数,对象或代码块,如下所示: 要么 问题答案: 首先-大多数类将永远不需要是线程安全的。使用YAGNI:仅当你知道实际上将要使用它(并对其进行测试)时,才应用线程安全性。 对于方法级的东西,有: 这也可以用于访问器(属性和事件): 请注意,默认情况下,类似字段的事件是同步的,而自动实现