Author:老九 计算机专业 可控之事 沉重冷静 不可控之事 乐观面对 85180586@qq.com 😄 😆 😵 😭 😰 😅 😢 😤 😍 ?? 😎 😩
👍 👎 💯 👏 🔔 🎁 ? 💣 ?? ?? 🌀 🙇 💋 🙏 💦 💩 ?? 💢 ———————————————— 版权声明:本文为CSDN博主「浦上青天」的原创文章
知识点
第三天总结
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关键字 使用时指定对象,本质是修改对应对象的“对象头”中的所标记 多个线程尝试同时获取一把锁,只有第一个获取锁的线程能够获取到锁,其他线程只能等,等到第一个线程释放了锁,才有机会获取到锁
第四天
volatile关键字
作用:保存内存可见性(其实就是编译器自身优化策略的bug) 禁止编译器进行刚才这种场景的优化(一个线程读,一个线程在写,修改对于读线程来说可能没生效 ) 速度:寄存器>内存>磁盘 牺牲了性能但是换来了结果的正确性 t1线程中的循环被编译器优化前,一开始是从内存中读取flag的值到cpu进行比较,优化后,后续的读内存并不是真正地读取,而是直接取刚才CPU中读到的数据,编译器认为flag没有改动,其实只是在当前线程中没有改动而已 作用位置:属性前面 若把后置++变成前置++,线程依旧不安全,,因为编译器已经优化了,是在cpu中找数,并不是在内存中,所以没有修改,依旧线程不安全
对象等待集
抢占式执行惹的祸 wait方法:当操作条件不成熟就等待 notify方法:当条件成熟时,通知指定的线程工作 等待集本质:程序员有一定的手段来干预线程的调度~
wait的工作过程
1.释放锁(得先有锁才能释放) 2.等待通知 3.当收到通知后,尝试重新获取锁,继续往下执行 注:wait方法必须在sychronized代码块内部使用,并且和锁的对象必须是一一对应的
代码块包裹快捷键
快捷键Ctrl + Alt + T
整理代码格式快捷键
快捷键Ctrl+ Alt + L
竟态条件问题
ATM举例:本来滑稽老铁要去取钱,结果ATM里没钱,然后告诉滑稽老铁释放锁wait,滑稽老铁一直玩手机,殊不知已经补充完钱了,滑稽老铁玩完手机开始专心盯着。
多线程的一些案例
单例模式
是一种常见的设计模式,设计模式就相当于”棋谱“,按照棋谱下棋,就不会差到哪去 场景:在代码中的有些概念,不应该存在多个实例,此时应该使用单例模式来解决
饿汉模式
public class ThreadDemo22 {
static class Singleton {
private Singleton() {
}
static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
public static void main(String[] args) {
Singleton s = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s == s2);
}
}
懒汉模式
public class ThreadDemo23 {
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 {
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.如果消费者消费的较快,盖帘上很快就空了,消费者就要等待,一直等到生产者生产了新的元素,消费者才能继续消费
先赞后看,养成习惯!!!^ _ ^??? 每天都更新知识点哦!!! 码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘记关注我哦!
|