两个线程同时执行同步块

som*_*rti 47 java multithreading synchronized thread-synchronization

下面是Thread进入同步块的代码,等待5秒然后退出.我已经Thread同时启动了两个实例.

期望是其中一个线程将拥有对同步对象的锁定,而另一个将等待.5秒后,当锁拥有者退出时,等待线程将执行.

但是,实际上,两个线程同时执行同步块并同时退出.

预期产出:

Thread-X <timeX> received the lock.
Thread-X <timeX+5s> exiting...
Thread-Y <timeY> received the lock.
Thread-Y <timeY+5s> exiting...
Run Code Online (Sandbox Code Playgroud)

实际产量:

Thread-X <time> received the lock.
Thread-Y <time> received the lock.
Thread-X <time+5s> exiting...
Thread-Y <time+5s> exiting...
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么吗?

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test2 {
public static void main(String[] args) {
    MyRunnable m = new MyRunnable();
    Thread t = new Thread(m);
    Thread t1 = new Thread(m);
    t.start();
    t1.start();
    }
}

class MyRunnable implements Runnable {
    @Override
    public void run() {
        synchronized (this) {
            try {
                SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
                Date date = new Date(System.currentTimeMillis());
                System.out.println(Thread.currentThread().getName() + " " + formatter.format(date) + " received the lock.");
                wait(5000);
                date = new Date(System.currentTimeMillis());
                System.out.println(Thread.currentThread().getName() + " " + formatter.format(date) + " exiting...");
            } catch(InterruptedException ie) {}
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*kus 60

答案在于java.lang.Object.wait(long),其文档说:

[...]此方法使当前线程(称为T)将自身置于此对象的等待集中,然后放弃此对象上的任何和所有同步声明.[...]


Sel*_*dek 32

使用

Thread.sleep(5000);
Run Code Online (Sandbox Code Playgroud)

Thread.sleep的JavaDocs:

导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数,具体取决于系统计时器和调度程序的精度和准确性.该线程不会失去任何监视器的所有权.


Ole*_*hov 13

Oracle Tutorials的以下引用解释了这种情况:

wait被调用时,线程释放锁,并暂停执行.

此外,只有一个线程可以执行synchronized由同一个对象保护的块!wait在您的示例中调用释放锁,从而允许另一个线程获取锁.