为什么 java wait/notify 必须与 synchronized 一起使用,jvm究竟做了些什么

Posted 技术专家

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么 java wait/notify 必须与 synchronized 一起使用,jvm究竟做了些什么相关的知识,希望对你有一定的参考价值。

这个课题提出来的是原先的线程并发解决的思路。目前解决线程并发,可以是lock接口结合condition  并发问题一直以来就是线程必不可少的话题。

java 是第一个内置对多线程支持的主流编程语言。在Java5之前,对多线程的支持主要是通过对块结构的同步实现的(synchronized配合wait,notify,notifyAll),Java5引入了java.util.concurrent包,提供了对多线程编程的更高层的支持。

今天我们来说说。java中,线程提供我们解决并发。同步的方法

  通常可以使用synchronized和notify,notifyAll以及wait方法来实现线程之间的数据传递及控制。对于对象obj来说:

  • obj.wait():该方法的调用,使得调用该方法的执行线程(T1)放弃obj的对象锁并阻塞,直到别的线程调用了obj的notifyAll方法、或者别的线程调用了obj的notify方法且JVM选择唤醒(T1),被唤醒的线程(T1)依旧阻塞在wait方法中,与其它的线程一起争夺obj的对象锁,直到它再次获得了obj的对象锁之后,才能从wait方法中返回。(除了notify方法,wait还有带有时间参数的版本,在等待了超过所设时间之后,T1线程一样会被唤醒,进入到争夺obj对象锁的行列;另外中断可以直接跳出wait方法)
  • obj.notify():该方法的调用,会从所有正在等待obj对象锁的线程中,唤醒其中的一个(选择算法依赖于不同实现),被唤醒的线程此时加入到了obj对象锁的争夺之中,然而该notify方法的执行线程此时并未释放obj的对象锁,而是离开synchronized代码块时释放。因此在notify方法之后,synchronized代码块结束之前,所有其他被唤醒的,等待obj对象锁的线程依旧被阻塞。
  • obj.notifyAll():与notify的区别是,该方法会唤醒所有正在等待obj对象锁的线程。(不过同一时刻,也只有一个线程可以拥有obj的对象锁)

要注意的是,wai,notify以及notifyAll方法的调用必须在相应的synchronized代码块之中

线程就是程序执行的路径。多线程,也就不难理解了,程序执行的多条路径,它们独立执行,但是又有莫大的联系

wait/notify字面意思是等待和告知

package com.huojg.test;

public class ThreadA {
    public static void main(String[] args) {
        ThreadB b = new ThreadB();
        b.start();// 主线程中启动另外一个线程
        System.out.println("b is start....");
        // 括号里的b是什么意思,应该很好理解吧
        synchronized (b) {
            try {
                System.out.println("Waiting for b to complete...");
                b.wait();// 这一句是什么意思,究竟谁等待?
                System.out.println("ThreadB is Completed. Now back to main thread");
            } catch (InterruptedException e) {
            }

        }
        System.out.println("Total is :" + b.total);
    }
}

class ThreadB extends Thread {
    int total;

    public void run() {
        synchronized (this) {
            System.out.println("ThreadB is running..");
            for (int i = 0; i <= 100; i++) {
                total += i;
            }
            System.out.println("total is" + total);
            notify();
        }
    }
}
b is start....
ThreadB is running..
total is5050
Waiting for b to complete...
ThreadB is Completed. Now back to main thread
Total is :5050

 

从程序运行的结果来看就不难理解wait/notify了,wait是让使用wait方法的对象等待,暂时先把对象锁给让出来,给其它持有该锁的对象用,其它对象用完后再告知(notify)等待的那个对象可以继续执行了,整个过程就是这样。wait/notify主要用于一个线程要等待另一个线程执行完后,然后得到执行结果的情况。

 

以上是关于为什么 java wait/notify 必须与 synchronized 一起使用,jvm究竟做了些什么的主要内容,如果未能解决你的问题,请参考以下文章

JAVA多线程之wait/notify

Java Object对象中的wait,notify,notifyAll的理解

为啥wait,notify和notifyAll必须在同步块或同步方法中调

java多线程wait notify join

Java多线程基础之wait,notify

JAVA同步锁机制 wait() notify() notifyAll()