为什么wait()总是在同步块中

时间:2022-11-04 15:35:11

We all know that in order to invoke Object.wait(), this call must be placed in synchronized block, otherwise an IllegalMonitorStateException is thrown. But what's the reason for making this restriction? I know that wait() releases the monitor, but why do we need to explicitly acquire the monitor by making particular block synchronized and then release the monitor by calling wait()?

我们都知道,为了调用Object.wait(),这个调用必须放在同步块中,否则将抛出一个IllegalMonitorStateException。但是限制的原因是什么呢?我知道wait()会释放监视器,但是为什么我们需要通过让特定的块同步,然后通过调用wait()释放监视器来明确地获取监视器?

What is the potential damage if it was possible to invoke wait() outside a synchronized block, retaining it's semantics - suspending the caller thread?

如果可能在同步块之外调用wait(),保留其语义——挂起调用者线程,那么潜在的损害是什么?

8 个解决方案

#1


190  

A wait() only makes sense when there is also a notify(), so it's always about communication between threads, and that needs synchronization to work correctly. One could argue that this should be implicit, but that would not really help, for the following reason:

wait()只有在有notify()时才有意义,所以它总是关于线程之间的通信,并且需要同步才能正确工作。有人可能会说,这应该是含蓄的,但这并没有真正的帮助,原因如下:

Semantically, you never just wait(). You need some condition to be satsified, and if it is not, you wait until it is. So what you really do is

从语义上讲,您永远不会等待()。你需要一些条件来实现,如果不是,你就等着它实现。所以你要做的就是。

if(!condition){
    wait();
}

But the condition is being set by a separate thread, so in order to have this work correctly you need synchronization.

但是条件是由一个单独的线程设置的,所以为了正确地完成这项工作,您需要同步。

A couple more things wrong with it, where just because your thread quit waiting doesn't mean the condition you are looking for is true:

它还有另外一些问题,仅仅因为线程停止等待并不意味着您正在寻找的条件是正确的:

  • You can get spurious wakeups (meaning that a thread can wake up from waiting without ever having received a notification), or

    您可以得到虚假的唤醒(意味着线程可以在从未收到通知的情况下从等待中醒来),或者

  • The condition can get set, but a third thread makes the condition false again by the time the waiting thread wakes up (and reacquires the monitor).

    条件可以得到设置,但是第三个线程在等待线程唤醒(并重新获得监视器)时再次使条件为假。

To deal with these cases what you really need is always some variation of this:

要处理这些情况,你真正需要的总是这种变化:

synchronized(lock){
    while(!condition){
        lock.wait();
    }
}

Better yet, don't mess with the synchronization primitives at all and work with the abstractions offered in the java.util.concurrent packages.

更好的是,完全不要打乱同步原语,使用java.util中提供的抽象。concurrent包。

#2


235  

What is the potential damage if it was possible to invoke wait() outside a synchronized block, retaining it's semantics - suspending the caller thread?

如果可能在同步块之外调用wait(),保留其语义——挂起调用者线程,那么潜在的损害是什么?

Let's illustrate what issues we would run into if wait() could be called outside of a synchronized block with a concrete example.

让我们用一个具体的示例说明如果在同步块之外调用wait()会遇到什么问题。

Suppose we were to implement a blocking queue (I know, there is already one in the API :)

假设我们要实现一个阻塞队列(我知道,API中已经有一个:)

A first attempt (without synchronization) could look something along the lines below

第一次尝试(没有同步)可以沿着下面的线查找一些内容

class BlockingQueue {
    Queue<String> buffer = new LinkedList<String>();

    public void give(String data) {
        buffer.add(data);
        notify();                   // Since someone may be waiting in take!
    }

    public String take() throws InterruptedException {
        while (buffer.isEmpty())    // don't use "if" due to spurious wakeups.
            wait();
        return buffer.remove();
    }
}

This is what could potentially happen:

这就是可能发生的情况:

  1. A consumer thread calls take() and sees that the buffer.isEmpty().

    使用者线程调用take()并看到buffer.isEmpty()。

  2. Before the consumer thread goes on to call wait(), a producer thread comes along and invokes a full give(), that is, buffer.add(data); notify();

    在消费者线程继续调用wait()之前,一个生产者线程出现并调用一个完整的give(),即buffer.add(data);notify();

  3. The consumer thread will now call wait() (and miss the notify() that was just called).

    现在,消费者线程将调用wait()(并忽略刚才调用的notify())。

  4. If unlucky, the producer thread won't produce more give() as a result of the fact that the consumer thread never wakes up, and we have a dead-lock.

    如果不幸,生产者线程不会产生更多的give(),因为消费者线程永远不会醒来,而且我们有一个死锁。

Once you understand the issue, the solution is obvious: Always perform give/notify and isEmpty/wait atomically.

一旦您理解了这个问题,解决方案是显而易见的:始终执行give/notify和isEmpty/wait。

Without going into details: This synchronization issue is universal. As Michael Borgwardt points out, wait/notify is all about communication between threads, so you'll always end up with a race condition similar to the one described above. This is why the "only wait inside synchronized" rule is enforced.

无需详细说明:这个同步问题是通用的。正如Michael Borgwardt所指出的,wait/notify都是关于线程之间的通信,因此您将总是以类似于上面描述的竞争条件结束。这就是为什么要强制执行“synchronized中惟一的等待”规则。


A paragraph from the link posted by @Willie summarizes it quite well:

@Willie发布的链接有一段很好的总结:

You need an absolute guarantee that the waiter and the notifier agree about the state of the predicate. The waiter checks the state of the predicate at some point slightly BEFORE it goes to sleep, but it depends for correctness on the predicate being true WHEN it goes to sleep. There's a period of vulnerability between those two events, which can break the program.

您需要一个绝对的保证,即侍者和通知者同意谓词的状态。在谓词进入睡眠之前,侍应生会检查谓词的状态,但它取决于谓词进入睡眠时的正确性。这两个事件之间有一段脆弱期,会破坏程序。

The predicate that the producer and consumer need to agree upon is in the above example buffer.isEmpty(). And the agreement is resolved by ensuring that the wait and notify are performed in synchronized blocks.

生产者和消费者需要同意的谓词在上面的示例buffer.isEmpty()中。并通过确保在同步块中执行等待和通知来解决协议。


This post has been rewritten as an article here: Java: Why wait must be called in a synchronized block

本文已被改写为一篇文章:Java:为什么必须在同步块中调用wait

#3


10  

@Rollerball is right. The wait() is called, so that the thread can wait for some condition to occur when this wait() call happens, the thread is forced to give up its lock.
To give up something, you need to own it first. Thread needs to own the lock first. Hence the need to call it inside a synchronized method/block.

@Rollerball是正确的。调用wait(),以便当这个wait()调用发生时,线程可以等待发生某些条件,从而迫使线程放弃它的锁。要放弃某样东西,你需要先拥有它。线程需要首先拥有锁。因此需要在同步方法/块中调用它。

Yes, I do agree with all the above answers regarding the potential damages/inconsistencies if you did not check the condition within synchronized method/block. However as @shrini1000 has pointed out, just calling wait() within synchronized block will not avert this inconsistency from happening.

是的,如果您没有在同步的方法/块中检查条件,我同意以上所有关于潜在损害/不一致的答案。但是正如@shrini1000所指出的,在synchronized块中调用wait()并不会避免这种不一致性。

Here is a nice read..

这是一篇很好的文章。

#4


3  

The problem it may cause if you do not synchronize before wait() is as follows:

如果在wait()之前不进行同步,可能会导致以下问题:

  1. If the 1st thread goes into makeChangeOnX() and checks the while condition, and it is true (x.metCondition() returns false, means x.condition is false) so it will get inside it. Then just before the wait() method, another thread goes to setConditionToTrue() and sets the x.condition to true and notifyAll().
  2. 如果第一个线程进入makeChangeOnX()并检查while条件,它是true (x. metcondition()返回false,表示x。条件是假的)所以它会进入它。然后,在wait()方法之前,另一个线程进入setConditionToTrue()并设置x。条件为true和notifyAll()。
  3. Then only after that, the 1st thread will enter his wait() method (not affected by the notifyAll() that happened few moments before). In this case, the 1st thread will stay waiting for another thread to perform setConditionToTrue(), but that might not happen again.
  4. 然后,只有在此之后,第一个线程才会进入他的wait()方法(不受前面几分钟发生的notifyAll()的影响)。在这种情况下,第1个线程将等待另一个线程执行setConditionToTrue(),但这种情况可能不会再次发生。

But if you put synchronized before the methods that change the object state, this will not happen.

但是,如果将synchronized放在更改对象状态的方法之前,就不会发生这种情况。

class A {

    private Object X;

    makeChangeOnX(){
        while (! x.getCondition()){
            wait();
            }
        // Do the change
    }

    setConditionToTrue(){
        x.condition = true; 
        notifyAll();

    }
    setConditionToFalse(){
        x.condition = false;
        notifyAll();
    }
    bool getCondition(){
        return x.condition;
    }
}

#5


2  

We all know that wait(), notify() and notifyAll() methods are used for inter-threaded communications. To get rid of missed signal and spurious wake up problems, waiting thread always waits on some conditions. e.g.-

我们都知道wait()、notify()和notifyAll()方法用于线程间通信。为了消除漏信号和虚假的唤醒问题,等待线程总是在某些条件下等待。例如,

boolean wasNotified = false;
while(!wasNotified) {
    wait();
}

Then notifying thread sets wasNotified variable to true and notify.

然后通知线程设置为true并通知。

Every thread has their local cache so all the changes first get written there and then promoted to main memory gradually.

每个线程都有自己的本地缓存,所以所有的更改首先被写到那里,然后逐渐升级到主内存。

Had these methods not invoked within synchronized block, the wasNotified variable would not be flushed into main memory and would be there in thread's local cache so the waiting thread will keep waiting for the signal although it was reset by notifying thread.

如果没有在同步块中调用这些方法,那么wasnotify变量将不会被刷新到主内存中,并且会在线程的本地缓存中,因此等待的线程将继续等待信号,尽管它是通过通知线程重置的。

To fix these types of problems, these methods are always invoked inside synchronized block which assures that when synchronized block starts then everything will be read from main memory and will be flushed into main memory before exiting the synchronized block.

为了修复这些类型的问题,这些方法总是在synchronized块中调用,它确保当synchronized块开始时,所有的内容都将从主内存中读取,并在退出synchronized块之前刷新到主内存中。

synchronized(monitor) {
    boolean wasNotified = false;
    while(!wasNotified) {
        wait();
    }
}

Thanks, hope it clarifies.

谢谢,希望它澄清。

#6


0  

directly from this java oracle tutorial:

直接从这个java oracle教程:

When a thread invokes d.wait, it must own the intrinsic lock for d — otherwise an error is thrown. Invoking wait inside a synchronized method is a simple way to acquire the intrinsic lock.

当一个线程调用d。等等,它必须拥有d的内部锁——否则会抛出错误。在同步方法中调用wait是获取内在锁的简单方法。

#7


0  

This basically has to do with the hardware architecture (i.e. RAM and caches).

这基本上与硬件架构(即RAM和缓存)有关。

If you don't use synchronized together with wait() or notify(), another thread could enter the same block instead of waiting for the monitor to enter it. Moreover, when e.g. accessing an array without a synchronized block, another thread may not see the changement to it...actually another thread will not see any changements to it when it already has a copy of the array in the x-level cache (a.k.a. 1st/2nd/3rd-level caches) of the thread handling CPU core.

如果不与wait()或notify()一起使用synchronized,则另一个线程可以输入相同的块,而不是等待监视器输入。此外,当访问没有同步块的数组时,另一个线程可能看不到对它的更改……实际上,当另一个线程在处理CPU核心的线程的x级缓存(即1 /2 /3级缓存)中已经有一个数组的副本时,另一个线程将看不到对它的任何更改。

But synchronized blocks are only one side of the medal: If you actually access an object within a synchronized context from a non-synchronized context, the object still won't be synchronized even within a synchronized block, because it holds an own copy of the object in its cache. I wrote about this issues here: https://*.com/a/21462631 and When a lock holds a non-final object, can the object's reference still be changed by another thread?

但是同步块只是奖章的一方面:如果您实际从非同步上下文访问同步上下文中的一个对象,那么即使在同步块中,该对象也不会被同步,因为它在其缓存中拥有该对象的一个自己的副本。我在这里写了这个问题:https://*.com/a/21462631,当一个锁持有一个非最终对象时,对象的引用是否还会被另一个线程更改?

Furthermore, I'm convinced that the x-level caches are responsible for most non-reproducible runtime errors. That's because the developers usually don't learn the low-level stuff, like how CPU's work or how the memory hierarchy affects the running of applications: http://en.wikipedia.org/wiki/Memory_hierarchy

此外,我确信x级缓存会导致大多数不可复制的运行时错误。这是因为开发人员通常不了解底层内容,比如CPU的工作方式,或者内存层次结构如何影响应用程序的运行:http://en.wikipedia.org/wiki/Memory_hierarchy

It remains a riddle why programming classes don't start with memory hierarchy and CPU architecture first. "Hello world" won't help here. ;)

为什么编程类不首先从内存层次结构和CPU体系结构开始仍然是个谜。“你好世界”在这里没用。,)

#8


0  

When you call notify() from an object t, java notifies a particular t.wait() method. But, how does java search and notify a particular wait method.

当从对象t调用notify()时,java会通知一个特定的t.wait()方法。但是,java如何搜索和通知一个特定的等待方法。

java only looks into the synchronized block of code which was locked by object t. java cannot search the whole code to notify a particular t.wait().

java只查看对象t锁定的同步代码块。java不能搜索整个代码以通知特定的t.wait()。

#1


190  

A wait() only makes sense when there is also a notify(), so it's always about communication between threads, and that needs synchronization to work correctly. One could argue that this should be implicit, but that would not really help, for the following reason:

wait()只有在有notify()时才有意义,所以它总是关于线程之间的通信,并且需要同步才能正确工作。有人可能会说,这应该是含蓄的,但这并没有真正的帮助,原因如下:

Semantically, you never just wait(). You need some condition to be satsified, and if it is not, you wait until it is. So what you really do is

从语义上讲,您永远不会等待()。你需要一些条件来实现,如果不是,你就等着它实现。所以你要做的就是。

if(!condition){
    wait();
}

But the condition is being set by a separate thread, so in order to have this work correctly you need synchronization.

但是条件是由一个单独的线程设置的,所以为了正确地完成这项工作,您需要同步。

A couple more things wrong with it, where just because your thread quit waiting doesn't mean the condition you are looking for is true:

它还有另外一些问题,仅仅因为线程停止等待并不意味着您正在寻找的条件是正确的:

  • You can get spurious wakeups (meaning that a thread can wake up from waiting without ever having received a notification), or

    您可以得到虚假的唤醒(意味着线程可以在从未收到通知的情况下从等待中醒来),或者

  • The condition can get set, but a third thread makes the condition false again by the time the waiting thread wakes up (and reacquires the monitor).

    条件可以得到设置,但是第三个线程在等待线程唤醒(并重新获得监视器)时再次使条件为假。

To deal with these cases what you really need is always some variation of this:

要处理这些情况,你真正需要的总是这种变化:

synchronized(lock){
    while(!condition){
        lock.wait();
    }
}

Better yet, don't mess with the synchronization primitives at all and work with the abstractions offered in the java.util.concurrent packages.

更好的是,完全不要打乱同步原语,使用java.util中提供的抽象。concurrent包。

#2


235  

What is the potential damage if it was possible to invoke wait() outside a synchronized block, retaining it's semantics - suspending the caller thread?

如果可能在同步块之外调用wait(),保留其语义——挂起调用者线程,那么潜在的损害是什么?

Let's illustrate what issues we would run into if wait() could be called outside of a synchronized block with a concrete example.

让我们用一个具体的示例说明如果在同步块之外调用wait()会遇到什么问题。

Suppose we were to implement a blocking queue (I know, there is already one in the API :)

假设我们要实现一个阻塞队列(我知道,API中已经有一个:)

A first attempt (without synchronization) could look something along the lines below

第一次尝试(没有同步)可以沿着下面的线查找一些内容

class BlockingQueue {
    Queue<String> buffer = new LinkedList<String>();

    public void give(String data) {
        buffer.add(data);
        notify();                   // Since someone may be waiting in take!
    }

    public String take() throws InterruptedException {
        while (buffer.isEmpty())    // don't use "if" due to spurious wakeups.
            wait();
        return buffer.remove();
    }
}

This is what could potentially happen:

这就是可能发生的情况:

  1. A consumer thread calls take() and sees that the buffer.isEmpty().

    使用者线程调用take()并看到buffer.isEmpty()。

  2. Before the consumer thread goes on to call wait(), a producer thread comes along and invokes a full give(), that is, buffer.add(data); notify();

    在消费者线程继续调用wait()之前,一个生产者线程出现并调用一个完整的give(),即buffer.add(data);notify();

  3. The consumer thread will now call wait() (and miss the notify() that was just called).

    现在,消费者线程将调用wait()(并忽略刚才调用的notify())。

  4. If unlucky, the producer thread won't produce more give() as a result of the fact that the consumer thread never wakes up, and we have a dead-lock.

    如果不幸,生产者线程不会产生更多的give(),因为消费者线程永远不会醒来,而且我们有一个死锁。

Once you understand the issue, the solution is obvious: Always perform give/notify and isEmpty/wait atomically.

一旦您理解了这个问题,解决方案是显而易见的:始终执行give/notify和isEmpty/wait。

Without going into details: This synchronization issue is universal. As Michael Borgwardt points out, wait/notify is all about communication between threads, so you'll always end up with a race condition similar to the one described above. This is why the "only wait inside synchronized" rule is enforced.

无需详细说明:这个同步问题是通用的。正如Michael Borgwardt所指出的,wait/notify都是关于线程之间的通信,因此您将总是以类似于上面描述的竞争条件结束。这就是为什么要强制执行“synchronized中惟一的等待”规则。


A paragraph from the link posted by @Willie summarizes it quite well:

@Willie发布的链接有一段很好的总结:

You need an absolute guarantee that the waiter and the notifier agree about the state of the predicate. The waiter checks the state of the predicate at some point slightly BEFORE it goes to sleep, but it depends for correctness on the predicate being true WHEN it goes to sleep. There's a period of vulnerability between those two events, which can break the program.

您需要一个绝对的保证,即侍者和通知者同意谓词的状态。在谓词进入睡眠之前,侍应生会检查谓词的状态,但它取决于谓词进入睡眠时的正确性。这两个事件之间有一段脆弱期,会破坏程序。

The predicate that the producer and consumer need to agree upon is in the above example buffer.isEmpty(). And the agreement is resolved by ensuring that the wait and notify are performed in synchronized blocks.

生产者和消费者需要同意的谓词在上面的示例buffer.isEmpty()中。并通过确保在同步块中执行等待和通知来解决协议。


This post has been rewritten as an article here: Java: Why wait must be called in a synchronized block

本文已被改写为一篇文章:Java:为什么必须在同步块中调用wait

#3


10  

@Rollerball is right. The wait() is called, so that the thread can wait for some condition to occur when this wait() call happens, the thread is forced to give up its lock.
To give up something, you need to own it first. Thread needs to own the lock first. Hence the need to call it inside a synchronized method/block.

@Rollerball是正确的。调用wait(),以便当这个wait()调用发生时,线程可以等待发生某些条件,从而迫使线程放弃它的锁。要放弃某样东西,你需要先拥有它。线程需要首先拥有锁。因此需要在同步方法/块中调用它。

Yes, I do agree with all the above answers regarding the potential damages/inconsistencies if you did not check the condition within synchronized method/block. However as @shrini1000 has pointed out, just calling wait() within synchronized block will not avert this inconsistency from happening.

是的,如果您没有在同步的方法/块中检查条件,我同意以上所有关于潜在损害/不一致的答案。但是正如@shrini1000所指出的,在synchronized块中调用wait()并不会避免这种不一致性。

Here is a nice read..

这是一篇很好的文章。

#4


3  

The problem it may cause if you do not synchronize before wait() is as follows:

如果在wait()之前不进行同步,可能会导致以下问题:

  1. If the 1st thread goes into makeChangeOnX() and checks the while condition, and it is true (x.metCondition() returns false, means x.condition is false) so it will get inside it. Then just before the wait() method, another thread goes to setConditionToTrue() and sets the x.condition to true and notifyAll().
  2. 如果第一个线程进入makeChangeOnX()并检查while条件,它是true (x. metcondition()返回false,表示x。条件是假的)所以它会进入它。然后,在wait()方法之前,另一个线程进入setConditionToTrue()并设置x。条件为true和notifyAll()。
  3. Then only after that, the 1st thread will enter his wait() method (not affected by the notifyAll() that happened few moments before). In this case, the 1st thread will stay waiting for another thread to perform setConditionToTrue(), but that might not happen again.
  4. 然后,只有在此之后,第一个线程才会进入他的wait()方法(不受前面几分钟发生的notifyAll()的影响)。在这种情况下,第1个线程将等待另一个线程执行setConditionToTrue(),但这种情况可能不会再次发生。

But if you put synchronized before the methods that change the object state, this will not happen.

但是,如果将synchronized放在更改对象状态的方法之前,就不会发生这种情况。

class A {

    private Object X;

    makeChangeOnX(){
        while (! x.getCondition()){
            wait();
            }
        // Do the change
    }

    setConditionToTrue(){
        x.condition = true; 
        notifyAll();

    }
    setConditionToFalse(){
        x.condition = false;
        notifyAll();
    }
    bool getCondition(){
        return x.condition;
    }
}

#5


2  

We all know that wait(), notify() and notifyAll() methods are used for inter-threaded communications. To get rid of missed signal and spurious wake up problems, waiting thread always waits on some conditions. e.g.-

我们都知道wait()、notify()和notifyAll()方法用于线程间通信。为了消除漏信号和虚假的唤醒问题,等待线程总是在某些条件下等待。例如,

boolean wasNotified = false;
while(!wasNotified) {
    wait();
}

Then notifying thread sets wasNotified variable to true and notify.

然后通知线程设置为true并通知。

Every thread has their local cache so all the changes first get written there and then promoted to main memory gradually.

每个线程都有自己的本地缓存,所以所有的更改首先被写到那里,然后逐渐升级到主内存。

Had these methods not invoked within synchronized block, the wasNotified variable would not be flushed into main memory and would be there in thread's local cache so the waiting thread will keep waiting for the signal although it was reset by notifying thread.

如果没有在同步块中调用这些方法,那么wasnotify变量将不会被刷新到主内存中,并且会在线程的本地缓存中,因此等待的线程将继续等待信号,尽管它是通过通知线程重置的。

To fix these types of problems, these methods are always invoked inside synchronized block which assures that when synchronized block starts then everything will be read from main memory and will be flushed into main memory before exiting the synchronized block.

为了修复这些类型的问题,这些方法总是在synchronized块中调用,它确保当synchronized块开始时,所有的内容都将从主内存中读取,并在退出synchronized块之前刷新到主内存中。

synchronized(monitor) {
    boolean wasNotified = false;
    while(!wasNotified) {
        wait();
    }
}

Thanks, hope it clarifies.

谢谢,希望它澄清。

#6


0  

directly from this java oracle tutorial:

直接从这个java oracle教程:

When a thread invokes d.wait, it must own the intrinsic lock for d — otherwise an error is thrown. Invoking wait inside a synchronized method is a simple way to acquire the intrinsic lock.

当一个线程调用d。等等,它必须拥有d的内部锁——否则会抛出错误。在同步方法中调用wait是获取内在锁的简单方法。

#7


0  

This basically has to do with the hardware architecture (i.e. RAM and caches).

这基本上与硬件架构(即RAM和缓存)有关。

If you don't use synchronized together with wait() or notify(), another thread could enter the same block instead of waiting for the monitor to enter it. Moreover, when e.g. accessing an array without a synchronized block, another thread may not see the changement to it...actually another thread will not see any changements to it when it already has a copy of the array in the x-level cache (a.k.a. 1st/2nd/3rd-level caches) of the thread handling CPU core.

如果不与wait()或notify()一起使用synchronized,则另一个线程可以输入相同的块,而不是等待监视器输入。此外,当访问没有同步块的数组时,另一个线程可能看不到对它的更改……实际上,当另一个线程在处理CPU核心的线程的x级缓存(即1 /2 /3级缓存)中已经有一个数组的副本时,另一个线程将看不到对它的任何更改。

But synchronized blocks are only one side of the medal: If you actually access an object within a synchronized context from a non-synchronized context, the object still won't be synchronized even within a synchronized block, because it holds an own copy of the object in its cache. I wrote about this issues here: https://*.com/a/21462631 and When a lock holds a non-final object, can the object's reference still be changed by another thread?

但是同步块只是奖章的一方面:如果您实际从非同步上下文访问同步上下文中的一个对象,那么即使在同步块中,该对象也不会被同步,因为它在其缓存中拥有该对象的一个自己的副本。我在这里写了这个问题:https://*.com/a/21462631,当一个锁持有一个非最终对象时,对象的引用是否还会被另一个线程更改?

Furthermore, I'm convinced that the x-level caches are responsible for most non-reproducible runtime errors. That's because the developers usually don't learn the low-level stuff, like how CPU's work or how the memory hierarchy affects the running of applications: http://en.wikipedia.org/wiki/Memory_hierarchy

此外,我确信x级缓存会导致大多数不可复制的运行时错误。这是因为开发人员通常不了解底层内容,比如CPU的工作方式,或者内存层次结构如何影响应用程序的运行:http://en.wikipedia.org/wiki/Memory_hierarchy

It remains a riddle why programming classes don't start with memory hierarchy and CPU architecture first. "Hello world" won't help here. ;)

为什么编程类不首先从内存层次结构和CPU体系结构开始仍然是个谜。“你好世界”在这里没用。,)

#8


0  

When you call notify() from an object t, java notifies a particular t.wait() method. But, how does java search and notify a particular wait method.

当从对象t调用notify()时,java会通知一个特定的t.wait()方法。但是,java如何搜索和通知一个特定的等待方法。

java only looks into the synchronized block of code which was locked by object t. java cannot search the whole code to notify a particular t.wait().

java只查看对象t锁定的同步代码块。java不能搜索整个代码以通知特定的t.wait()。