两个线程同时执行同步块

时间:2018-09-24 10:28:18

标签: 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...
  

实际输出:

Thread-X <time> received the lock.
Thread-Y <time> received the lock.
Thread-X <time+5s> exiting...
Thread-Y <time+5s> exiting...

我在这里想念东西吗?

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) {}
        }
    }
}

3 个答案:

答案 0 :(得分:60)

答案位于java.lang.Object.wait(long),其文档显示:

  

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

答案 1 :(得分:32)

使用

Thread.sleep(5000);

JavaDocs for Thread.sleep:

  

使当前正在执行的线程在指定的毫秒数内进入睡眠状态(暂时停止执行),这取决于系统计时器和调度程序的精度和准确性。线程不会失去任何监视器的所有权。

答案 2 :(得分:13)

Oracle Tutorials中的以下引号说明了这种情况:

  

调用wait时,线程释放锁并挂起   执行。

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