【问题标题】:different states in synchronization不同状态同步
【发布时间】:2012-04-18 16:39:55
【问题描述】:

我有两个线程thread1和thread2

线程1内

synchronized(lock) {  
    lock.wait();  
    if(lock == null)
        {execute1}  
    if(lock != null)  
        {execute2}   
}  

在线程 2 内

synchronized(lock) {  
    lock.notify();  
    lock = null;  
}  

首先调用thread1,然后调用thread2。
在 thread1 调用 wait 之后,它释放它的锁。并且 thread2 调用 notify 并将 lock 设置为 null。
现在,当 thread1 再次尝试获取锁时,为什么它没有抛出任何异常。由于锁被设置为 null 并且 thread1 尝试获取该锁,所以它在尝试获取锁时不应该抛出空指针异常。
如果它没有抛出任何异常,则 thread1 仍在读取锁值不为空。那么它不应该执行语句 {execute2} 吗?

【问题讨论】:

  • lock 声明在哪里?它是Runnable/Thread 扩展类的实例变量吗?它是方法的局部变量吗?我们需要有关代码的更多详细信息。
  • 好吧,如果lock 真的是null,你的lock.wait() 会抛出一个NPE。在任何情况下,您都在lock 上进行同步,然后将其设置为null。发生这种情况时,无法保证对 lock 的更改可见。您应该在 final 对象上进行同步。
  • lock 是主类 A 中 Object 类型的实例变量。 lock = new Object();两个线程都扩展为可运行的。我正在从同一个 A 类启动两个线程。首先调用 thread1,然后调用 thread2。

标签: java


【解决方案1】:

你在一个对象上同步,而不是一个变量。监视器属于对象。

如果锁指向一个非空对象,然后你等待它,将lock 设置为空并不意味着什么,因为它是@987654324 指向的对象@ 等待并通知。

然后,当 thread1 重新获得控制权时,将调用 execute1,因为此时 变量 为空。

编辑

由于您似乎误解了整个 wait()notify() 语义,因此这里引用了来自 the Javadoc 的相关引用(强调我的):

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

这应该向您表明该变量在用于指向您同步/等待/通知的对象之前完全不相关。

【讨论】:

  • 如果一个线程被通知,是不是应该再次获取锁。如果它应该获取锁它将使用什么对象,它会尝试获取同步块中的变量引用的对象上的锁(同步(锁)中的锁引用的对象)还是尝试获取在调用wait时获取变量引用的对象上的锁like(调用lock.wait()时锁引用的对象)
  • @vjk:在调用wait() 将控制权返回给您的方法之前,它会再次获得锁。该变量仅用于确定要在哪个对象上调用wait()(就像您调用任何其他实例方法时一样!),显然wait() 不知道您的方法的局部变量。查看 Object.wait() 的 javadoc。
猜你喜欢
  • 1970-01-01
  • 2018-11-29
  • 1970-01-01
  • 2021-09-05
  • 2023-03-10
  • 1970-01-01
  • 2013-07-22
  • 2018-10-12
  • 1970-01-01
相关资源
最近更新 更多