前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >快速掌握并发编程---线程阻塞与唤醒

快速掌握并发编程---线程阻塞与唤醒

作者头像
田维常
发布2020-10-23 15:45:48
4190
发布2020-10-23 15:45:48
举报

synchronized 结合 java.lang.Object 对象中的wait()notify()notifyAll()

应用

线程A

代码语言:javascript
复制
public class ThreadA  extends Thread{
    private Object lock;

    public ThreadA(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock){
            System.out.println("ThreadA---start");
            try {
                //实现线程阻塞
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("ThreadA---end");
        }
    }
}

线程B

代码语言:javascript
复制
public class ThreadB extends Thread {
    private Object lock;

    public ThreadB(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock) {
            System.out.println("ThreadB---start");
            //实现线程的唤醒
            lock.notify();
            System.out.println("ThreadB---end");
        }
    }
}

测试

代码语言:javascript
复制
public class WaitDemo {
    public static void main(String[] args) {
        Object lock = new Object();
        ThreadA threadA = new ThreadA(lock);
        threadA.start();
        ThreadB threadB = new ThreadB(lock);
        threadB.start();
    }
}

运行输出

代码语言:javascript
复制
ThreadA---start
ThreadB---start
ThreadB---end
ThreadA---end

ThreadA阻塞挂起,ThreadB唤醒,ThreadA被唤醒。

上面这段代码我们会发现被阻塞的线程什么时候被唤醒,取决于获得锁的线程什么时候执行完同步代码块并且释放锁。

那怎么做到显示控制呢?我们就需要借 助 一 个 信 号机 制 :在 Object 对 象 中 ,提 供 了wait/notify/notifyall,可以用于控制线程的状态

wait/notify/notifyAll 基本概念
  • wait:表示持有对象锁的线程 A 准备释放对象锁权限,释放 CPU资源并进入等待状态。
  • notify:表示持有对象锁的线程 A 准备释放对象锁权限,通知 JVM唤醒某个竞争该对象锁的线程 X。线程 A 同步代码块执行结束并且释放了锁之后,线程 X 直接获得对象锁权限,其他竞争线程继续等待(即使线程 X 同步完毕,释放对象锁,其他竞争线程仍然等待,直至有新的 notify ,notifyAll 被调用)。
  • notifyAll:notifyall 和 notify 的区别在于,notifyAll 会唤醒所有竞争同一个对象锁的所有线程,当已经获得锁的线程A 释放锁之后,所有被唤醒的线程都有可能获得对象锁权限(notifyAll唤醒等待队列中所有线程,然后所有被唤醒的线程重新进入锁竞争)。

需要注意的是:

三个方法都必须在 synchronized 同步关键字所限定的作用域中调用 ,否则会报错

java.lang.IllegalMonitorStateException

意思是因为没有同步,所以线程对对象锁的状态是不确定的,不能调用这些方法。另外,通过同步机制来确保线程从 wait 方法返回时能够感知到感知到 notify 线程对变量做出的修改waity /notify 。

waity /notify 的基本原理

注意两个队列:

  • 等待队列:notifyAll/notify唤醒的就是等待队列中的线程;
  • 同步线程:就是竞争锁的所有线程,等待队列中的线程被唤醒后进入同步队列。
sleep与wait的区别
sleep
  • 让当前线程休眠指定时间。
  • 休眠时间的准确性依赖于系统时钟和CPU调度机制。
  • 不释放已获取的锁资源,如果sleep方法在同步上下文中调用,那么其他线程是无法进入到当前同步块或者同步方法中的。
  • 可通过调用interrupt()方法来唤醒休眠线程。
  • sleep是Thread里的方法
wait
  • 让当前线程进入等待状态,当别的其他线程调用notify()或者notifyAll()方法时,当前线程进入就绪状态
  • wait方法必须在同步上下文中调用,例如:同步方法块或者同步方法中,这也就意味着如果你想要调用wait方法,前提是必须获取对象上的锁资源
  • 当wait方法调用时,当前线程将会释放已获取的对象锁资源,并进入等待队列,其他线程就可以尝试获取对象上的锁资源。
  • wait是Object中的方法
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java后端技术全栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 应用
  • wait/notify/notifyAll 基本概念
  • waity /notify 的基本原理
  • sleep与wait的区别
    • sleep
      • wait
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档