JavaEE初阶 多线程 3

volatile关键字

上个博客说过造成线程安全问题还有一个可解决的原因,内存可见性

volatile 修饰的变量,能够保证"内存可⻅性"

java 复制代码
  private static int flag=0;
    public static void main(String[] args) {
        Thread t0=new Thread(()->{
            while (flag==0){
                System.out.println("t0");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("t0结束");
        });
        Thread t1 = new Thread(() -> {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入 flag 的值: ");
            flag = scanner.nextInt();
            System.out.println("t2 结束");
        });
        t0.start();
        t1.start();
    }

上述代码运行起来结果不会出现t0结束,原因就是t0进程的对flag的load取数指令被编译器优化掉了,while循环很快,每次读到flag的值相同,而load的开销相比于compare比较指令大多,因此被优化为cmp

当t1对flag变量进⾏修改,此时t0感知不到flag的变化

加volatile 关键字

java 复制代码
  private static volatile int flag=1;

结果:

wait 和notify

线程之间是抢占式执⾏的,因此线程之间执⾏的先后顺序难以预知,但可以让调度到该线程时使用wait使该线程阻塞等待,直到其他线程使用notify唤醒

wait()/wait(long timeout): 让当前线程进⼊等待状态.

notify() / notifyAll(): 唤醒在当前对象上等待的线程.

注 意 : wait,notify, notifyAll 都是 Object 类的⽅法

wait()⽅法 :

使当前执⾏代码的线程进⾏等待.(把线程放到等待队列中)

过程

1.释放当前的锁

2.满⾜⼀定条件时被唤醒

3.重新尝试获取这个锁

java 复制代码
Object locker = new Object();

 Thread t1=new Thread(()->{
   synchronized (locker) {
   System.out.println("等待中");
   locker.wait();
   System.out.println("等待结束");
   }
}

notify()⽅法:

1.唤醒等待的线程,如果有多个线程等待,则有线程调度器随机挑选出⼀个呈wait状态的线程。(并没有"先来后到")

2.在notify()⽅法后,当前线程不会⻢上释放该对象锁,要等到执⾏notify()⽅法的线程将程序执⾏ 完,也就是退出同步代码块之后才会释放对象锁。

java 复制代码
Thread t2=new Thread(()->{
synchronized (locker){
                System.out.println("notify之前");
                locker.notify();
                System.out.println("notify之后");
            }

notifyAll()⽅法: notify⽅法只是唤醒某⼀个等待线程.使⽤notifyAll⽅法可以⼀次唤醒所有的等待线程.

wait与sleep区别

1.wait是Object类中的一个方法,sleep是Thread类中的一个方法;

2.wait必须在synchronized修饰的代码块或方法中使用,sleep方法可以在任何位置使用;

3.wait被调用后当前线程进入BLOCK状态并释放锁,并可以通过notify和notifyAll方法进行唤醒;sleep被调用后当前线程进入TIMED_WAIT状态,不涉及锁相关的操作;

相关推荐
懂点Tech15 小时前
ctfshow misc28:GIF 高度修改解题与脚本实现
开发语言·windows·python
云和数据.ChenGuang15 小时前
Python 重写(Override)深度解析:从 MRO 到 super() 的完整机制
java·开发语言·人工智能·python·langchain·1024程序员节
摇滚侠15 小时前
《On Java 中文版 基础卷》阅读笔记 实现隐藏 12
java·数据库·笔记
美狐美颜SDK开放平台16 小时前
视频美颜SDK试用DEMO阶段应该测试什么?直播APP接入实操指南
开发语言·人工智能·深度学习·音视频·美颜sdk·直播美颜sdk·第三方美颜sdk
dtq042416 小时前
C++小案例 - 日志实战
开发语言·c++
星夜离尘5616 小时前
MATLAB ADC 码流触顶诊断:命中数、缺口分段与削顶不可辨识性
开发语言·matlab
码匠许师傅17 小时前
【C++三方组件】Qt 概览:桌面 C++ 的事实标准与许可证三轨
开发语言·c++·qt
码匠许师傅18 小时前
【C++三方组件】POCO:跨平台系统编程全家桶
开发语言·c++
silvamux_18 小时前
10款模型写种草笔记:可发布性、返工来源与成本数据缺口复盘
java·数据库·笔记
bkspiderx18 小时前
基于Socket的广播通信及C语言实现详解
c语言·开发语言·socket·广播·socket的广播通信