Author:老九
计算机专业
可控之事 沉重冷静 不可控之事 乐观面对
85180586@qq.com
☺️
❓ ❤️ ☕️ ❗️
————————————————
版权声明:本文为CSDN博主「浦上青天」的原创文章
第三天总结第四天
volatile关键字对象等待集
wait的工作过程
代码块包裹快捷键整理代码格式快捷键 竟态条件问题 多线程的一些案例
单例模式
饿汉模式懒汉模式 阻塞队列案例
生产者消费者模型
知识点
第四天 volatile关键字1.线程的基本概念和进程的区别
2.控制线程
a)创建(5种)Thread
b)中断(2种)
c)等待join
d)获取线程实例
e)线程休眠(sleep)
3.线程状态
a)NEW
b)RUNNABLE
c)WAITING
d)TIMED_WAITING
e)BLOCKED
f)TERMINATED
4.线程安全
a)概念:多线程执行某个逻辑的时候,没有产生逻辑错误,就是线程安全的
b)成因:
i)抢占式执行
ii)修改操作不是原子的
iii)多个线程同时修改同一个变量
iv)内存可见性
v)指令重排序
c)如何解决:加锁
sychronized关键字
使用时指定对象,本质是修改对应对象的“对象头”中的所标记
多个线程尝试同时获取一把锁,只有第一个获取锁的线程能够获取到锁,其他线程只能等,等到第一个线程释放了锁,才有机会获取到锁
对象等待集作用:保存内存可见性(其实就是编译器自身优化策略的bug)
禁止编译器进行刚才这种场景的优化(一个线程读,一个线程在写,修改对于读线程来说可能没生效 )
速度:寄存器>内存>磁盘
牺牲了性能但是换来了结果的正确性
t1线程中的循环被编译器优化前,一开始是从内存中读取flag的值到cpu进行比较,优化后,后续的读内存并不是真正地读取,而是直接取刚才CPU中读到的数据,编译器认为flag没有改动,其实只是在当前线程中没有改动而已
作用位置:属性前面
若把后置++变成前置++,线程依旧不安全,,因为编译器已经优化了,是在cpu中找数,并不是在内存中,所以没有修改,依旧线程不安全
wait的工作过程抢占式执行惹的祸
wait方法:当操作条件不成熟就等待
notify方法:当条件成熟时,通知指定的线程工作
等待集本质:程序员有一定的手段来干预线程的调度~
代码块包裹快捷键1.释放锁(得先有锁才能释放)
2.等待通知
3.当收到通知后,尝试重新获取锁,继续往下执行
注:wait方法必须在sychronized代码块内部使用,并且和锁的对象必须是一一对应的
快捷键Ctrl + Alt + T
整理代码格式快捷键快捷键Ctrl+ Alt + L
竟态条件问题多线程的一些案例 单例模式ATM举例:本来滑稽老铁要去取钱,结果ATM里没钱,然后告诉滑稽老铁释放锁wait,滑稽老铁一直玩手机,殊不知已经补充完钱了,滑稽老铁玩完手机开始专心盯着。
饿汉模式是一种常见的设计模式,设计模式就相当于”棋谱“,按照棋谱下棋,就不会差到哪去
场景:在代码中的有些概念,不应该存在多个实例,此时应该使用单例模式来解决
public class ThreadDemo22 {
//先创建一个表示单例的类
//Singleton这个类只能有一个实例
//饿汉模式的单例实现,"饿"指的是,只要类被加载,实例就会立刻拆功能键(实例创建的时机比较早)
static class Singleton {
//把构造方法变成私有,此时在该类外部就无法new这个类的实例
private Singleton() {
}
//再来创建一个static的成员,表示Singleton类的唯一的实例
//Static 和 类相关,和实例无关,类在内存中只有一份,static成员也就只有一份
static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
public static void main(String[] args) {
//此处的getInstance就是获取该类实例的唯一方式,不应该使用其他方式来创建实例
Singleton s = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s == s2);
}
}
懒汉模式
public class ThreadDemo23 {
//使用懒汉模式来实现,Singleton类被加载的时候,不会立刻实例化
//等到第一次使用这个实例的时候,再实例化
static class Singleton{
private Singleton(){}
private static Singleton instance = null;
public static Singleton getInstance()
{
if(instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
饿汉模式是线程安全的
懒汉模式线程就不安全的,如果要是已经把实例创建好了,后面再去并发调用getInstance,就是线程安全的了
完美的懒汉模式代码
public class ThreadDemo23 {
//使用懒汉模式来实现,Singleton类被加载的时候,不会立刻实例化
//等到第一次使用这个实例的时候,再实例化
static class Singleton {
private Singleton() {
}
private volatile static Singleton instance = null;
//加锁就是为了代码块的原子性
static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
}
阻塞队列案例1.加锁,保证线程安全
2.双重if保证效率
3.volatile避免内存可见性引来的问题
生产者消费者模型是并发编程中的重要基础组件,帮助我们实现"生产者-消费者"模型
如果入队列操作太快,队列满了,继续入队列就会阻塞,一直阻塞到有其他线程去消费队列了,才能入队列。
如果出队列操作太快,队列空了,继续出队列,也会阻塞,一直阻塞到有其他线程生产了元素,才能继续出队列
符合先进先出的特点~
是一种典型的处理并发编程的模式,跟报饺子皮一样
重要的特点:
1.如果生产者生产的较快,盖帘上很快就放满了饺子皮~生产者就要等待,一直等到消费者又消费了一些数据,交易场所上有了空位,才能继续生产
2.如果消费者消费的较快,盖帘上很快就空了,消费者就要等待,一直等到生产者生产了新的元素,消费者才能继续消费
先赞后看,养成习惯!!!^ _ ^♥♥♥
每天都更新知识点哦!!!
码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘记关注我哦!



