同步并通知执行顺序和范围

bam*_*222 4 java multithreading synchronization

1)一旦在该线程同步代码块内调用notify,或者一旦退出同步代码块,线程是否会立即放弃它的锁?

例如,似乎在不指定线程优先级的情况下,我的 Process 类将从上到下执行。Produce 将首先被调用,它将执行一些操作,然后 wait(); Consumer会运行,然后它会调用notify(),它将打印“Done”,或者会先有5秒的延迟,然后打印“Done”?

2)另外,如果我有第三个同步方法/线程,它不等待或通知而只是运行,我可以先验地预测我的操作执行的顺序吗?

3)最后,notify()如何知道要“唤醒”哪个线程?例如,假设我有多个进程,每个进程同时执行 2 个线程,并且每个进程 A、B 和 C 都会调用 notification()。每个notify()对于每个进程来说都是本地的吗?换句话说,如果进程A调用notify(),是否可以唤醒进程B中正在等待的线程?到目前为止,我已经看到了在(this)上调用了synchronized,这让我认为它引用了一个特定的对象类,这反过来又让我认为在synchronized块中调用的所有notify()都受到synchronized( this) 指的是,所以不会有交叉。

public class Process {

public void produce( ) {
  synchronized(this) {
   // do stuff
    wait( );
     System.out.println("Done");
    }
}


public void consume( ) {
    synchronized(this) {
    // stuff
    notify(); 
    Thread.sleep(5000);
    }
}
}
Run Code Online (Sandbox Code Playgroud)

Sot*_*lis 5

您可以编写一个简单的程序来测试这一点

public static void main(String[] args) throws Exception {
    final Process e = new Process();        
    Thread t = new Thread(new Runnable() {          
        @Override
        public void run() {
            try {
                Thread.sleep(10);
                e.consume();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    t.start();
    e.produce();
}
Run Code Online (Sandbox Code Playgroud)

该程序等待 5000 毫秒并打印

Done
Run Code Online (Sandbox Code Playgroud)

至于你的问题

1)一旦在该线程同步代码块内调用notify,或者一旦退出同步代码块,线程是否会立即放弃它的锁?

notify()状态的 javadoc

如果有任何线程正在等待该对象,则选择唤醒其中一个线程。该选择是任意的,并且由实现自行决定。**strong text线程通过调用其中一个等待方法来等待对象的监视器。

被唤醒的线程将无法继续,直到当前线程放弃该对象上的锁

所以,不,线程在调用时不会放弃对锁的控制notify()。当代码退出synchronized块时就会发生这种情况。

2)另外,如果我有第三个同步方法/线程,它不等待或通知而只是运行,我可以先验地预测我的操作执行的顺序吗?

你可以估计,但不能确定。执行由线程调度程序自行决定。

3)最后,notify()如何知道要“唤醒”哪个线程?

打电话不知道。线程调度程序知道并选择。你无法控制这一点。

wait()notify()状态的 javadoc

此方法只能由该对象监视器的所有者的线程调用。

IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。

因此,只有当您位于在synchronized该对象上同步的块内时,才能在该对象上调用它们。

在您的代码示例中,调用

wait();
Run Code Online (Sandbox Code Playgroud)

正在隐式地做

this.wait();
Run Code Online (Sandbox Code Playgroud)

  • @TheLostMind 当然,但这无关紧要。您需要知道的是,锁定在“同步”块的持续时间内保持不变。时间片仅适用于执行线程,不适用于休眠线程。 (2认同)