Java用不同的方法同步同一对象上的块

我试图了解Java中同步块的概念。从我阅读的文档中,我了解到,如果我们获得一个锁(使用实例变量的同步块),那么我们将无法在该类中的同一对象上获得同步锁。但是,当我尝试使用以下代码片段尝试时,我发现我的理解是错误的。

即我可以同时在两种不同的方法中获取锁(同一实例变量上的同步块)。当线程启动时,它将进入运行方法并无限期等待,并且不会从同步块中退出。同时,如果我使用同一线程调用stop方法,它将进入同步块并执行notify语句。我搜索了Java文档,但找不到任何文档。

这是代码片段:

public class MyClass extends Thread
{
    private Object lock = new Object(); 
    public void run()
    {
      synchronized(lock)
      {
          lock.wait()
      }
      //other code
    }
    public void stop()
    {
      synchronized(lock)
      {
          lock.notify()
      }
      //other code
    } 
}

这是我如何管理MyClass线程的代码片段:

public class MyClassAdmin 
{
    MyClass _myclass;
    public MyClassAdmin()
    {
        _myclass=new MyClass();
        _myclass.start();
    }
    public void stop()
    {
    _myclass.stop();
    }
    public static void main(String args[])
    {
    MyClassAdmin _myclassAdmin=new MyClassAdmin();
    _myclassAdmin.stop();
    }
}

根据我的理解,当线程启动时,它将获取对“ lock”对象(MyClass的run方法中的同步块)的锁定。当我调用stop方法时,它应该无限期地等待,直到run方法从同步块中出来(这种情况下永远不会发生)。但是当我执行时,调用stop方法获得了对“ lock”对象的锁定,并通知了该对象,从而导致线程关闭。

内森·休斯(Nathan Hughes)

两种方法都使用相同的锁。如果您的MyClass线程恰好在主线程可以调用stop方法之前开始等待,则您的stop方法仍然可以继续,因为等待的线程释放了锁。一旦线程进入wait方法,它将在休眠之前释放锁定,并且直到退出exit方法才重新获取该锁定。

这是Object#wait的相关API文档,第二段介绍了我上面所描述的关于wait如何释放锁的内容。请注意说明您必须在循环中调用此方法的部分,否则您将遇到顺序依赖性错误,当通知到达主线程时,该依赖关系错误可能导致等待线程挂起,而另一个线程才可以开始等待。

公共最后一个void wait()抛出InterruptedException

使当前线程等待,直到另一个线程为此对象调用notify()方法或notifyAll()方法。换句话说,此方法的行为与仅执行调用wait(0)的行为完全相同。

当前线程必须拥有该对象的监视器。线程释放此监视器的所有权,并等待直到另一个线程通过调用notify方法或notifyAll方法通知等待在该对象监视器上等待的线程唤醒。然后线程等待,直到它可以重新获得监视器的所有权并恢复执行。

与一个参数版本中一样,可能会产生中断和虚假唤醒,并且应始终在循环中使用此方法:

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait();
     ... // Perform action appropriate to condition
 }  

此方法只能由作为该对象的监视器的所有者的线程调用。有关线程可以成为监视器所有者的方式的描述,请参见notify方法。

可以理解,这是一个玩具示例,但是子类化Thread和重写Thread方法是令人困惑的。使用Runnable而不是Thread的原因之一是没有机会通过错误地重写Thread方法而导致问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Java用不同的方法同步同一对象上的块

来自分类Dev

在同一对象上使用不同的动作(方法)创建死锁情况?

来自分类Dev

多线程访问同一对象上的同步方法和非同步方法

来自分类Dev

为什么我的同步代码块似乎忽略了同一对象上的另一个正在等待的同步块?

来自分类Dev

同一对象上的stringByAppendingString

来自分类Dev

同一对象的链接方法

来自分类Dev

将同一对象存储在不同的数组中

来自分类Dev

获取同一对象的不同JSON表示形式

来自分类Dev

同一对象的不同内存地址

来自分类Dev

同一对象在不同的类中?

来自分类Dev

同一对象的不同类型

来自分类Dev

为什么同一对象的不同方法具有相同的“ id”?

来自分类Dev

Java 8流:基于不同的属性多次映射同一对象

来自分类Dev

Java中同一对象内的对象列表

来自分类Dev

javascript在同一对象上的多个命令

来自分类Dev

mstest如何创建可在同一对象上运行的测试方法(累加)?

来自分类Dev

PHP json_encode在2个不同的服务器上为同一对象返回不同的值

来自分类Dev

如何模拟更新同一对象的函数/方法?

来自分类Dev

Java Play框架对同一对象的异步操作

来自分类Dev

在Java中销毁对同一对象的多个引用

来自分类Dev

创建同一对象的多个实例时,Java 是否复制方法实现?

来自分类Dev

由同一对象同步的等待通知不起作用

来自分类Dev

ActionListener()引用同一对象

来自分类Dev

Qt在两个不同的线程中运行同一对象的2个方法

来自分类Dev

休眠:为列表中的同一对象引用生成不同的(唯一的)ID

来自分类Dev

从同一对象的不同实例中触发另一个实例的函数

来自分类Dev

选择对象与在同一对象上使用foreach之间的区别

来自分类Dev

Ramda Js:使用来自同一对象的值在对象上设置属性

来自分类Dev

REST服务和具有不同字段的同一对象的多种表示形式

Related 相关文章

  1. 1

    Java用不同的方法同步同一对象上的块

  2. 2

    在同一对象上使用不同的动作(方法)创建死锁情况?

  3. 3

    多线程访问同一对象上的同步方法和非同步方法

  4. 4

    为什么我的同步代码块似乎忽略了同一对象上的另一个正在等待的同步块?

  5. 5

    同一对象上的stringByAppendingString

  6. 6

    同一对象的链接方法

  7. 7

    将同一对象存储在不同的数组中

  8. 8

    获取同一对象的不同JSON表示形式

  9. 9

    同一对象的不同内存地址

  10. 10

    同一对象在不同的类中?

  11. 11

    同一对象的不同类型

  12. 12

    为什么同一对象的不同方法具有相同的“ id”?

  13. 13

    Java 8流:基于不同的属性多次映射同一对象

  14. 14

    Java中同一对象内的对象列表

  15. 15

    javascript在同一对象上的多个命令

  16. 16

    mstest如何创建可在同一对象上运行的测试方法(累加)?

  17. 17

    PHP json_encode在2个不同的服务器上为同一对象返回不同的值

  18. 18

    如何模拟更新同一对象的函数/方法?

  19. 19

    Java Play框架对同一对象的异步操作

  20. 20

    在Java中销毁对同一对象的多个引用

  21. 21

    创建同一对象的多个实例时,Java 是否复制方法实现?

  22. 22

    由同一对象同步的等待通知不起作用

  23. 23

    ActionListener()引用同一对象

  24. 24

    Qt在两个不同的线程中运行同一对象的2个方法

  25. 25

    休眠:为列表中的同一对象引用生成不同的(唯一的)ID

  26. 26

    从同一对象的不同实例中触发另一个实例的函数

  27. 27

    选择对象与在同一对象上使用foreach之间的区别

  28. 28

    Ramda Js:使用来自同一对象的值在对象上设置属性

  29. 29

    REST服务和具有不同字段的同一对象的多种表示形式

热门标签

归档