Java 并发笔记

Java 并发笔记

JVM角度理解进程和线程的关系

线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。线程执行开销小,但不利于资源的管理和保护;而进程正相反。程序计数器应该是私有的。

线程切换后能恢复到正确的执行位置。
为了保证线程中的局部变量不被别的线程访问到,虚拟机栈和本地方法栈是线程私有的
线程安全和不安全
线程安全分析
成员变量和静态变量

成员变量和静态变量被共享了,且代码有读写操作,则代码是是临界区,则需要考虑线程安全问题。

局部变量
  • 局部变量线程安全
  • 局部变量的引用对象,如果逃离了方法的作用范围,则需要考虑线程安全。
局部变量暴露引用

eg. 子类重写父类方法,创建新线程导致线程变量被线程共享,且有读写操作。

  • 父类方法用private或final关键词字防止方法被重写。体系了开闭原则。
线程的生命周期和状态
  • NEW
  • RUNNABLE(running和ready切换)
  • BLOCKED:线程阻塞,需要等待锁释放
  • WAITING:线程等待其他线程通知或中断
  • TIME_WAITING
  • TERMINATED
产生死锁的必要条件
  • 互斥条件:该资源任意时刻只能被一个线程占用
  • 请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
  • 不剥夺条件
  • 循环等待
预防死锁?
  • 一次性申请所有资源:破坏请求与保持
  • 破坏不剥夺条件
  • 破坏循环等待条件
避免死锁

volatile

happens-before 原则
  • 程序顺序规则:一个线程内按照代码顺序,书写在前面的操作 happens-before 于书写在后面的操作
  • 解锁规则:解锁happens-before于加锁
  • volatile 变量规则:对 volatile 变量的写操作的结果对于发生于其后的任何操作都是可见的。
  • 传递规则
  • 线程启动规则:Thread对象的start()方法happens-before线程的每一个动作。
CAS: 输入2个值:旧值 和 新值,1、比较旧值有没有变化 -》 没变化则交换成新值。
乐观锁: 版本号,CAS
乐观锁存在的问题:
  • ABA 解决:版本号或时间戳
  • CAS经常自旋来重试,就是不成功就一直循环执行直到成功。
  • 只能保证一个共享变量的原子操作 --> AtomicReference类保证引用对象间原子性。

构造方法不能使用 synchronized 关键字修饰。

线程池

如何创建线程池?

通过ThreadPoolExecutor构造函数来创建线程池。
通过 Executor 框架的工具类 Executors 来创建。
  • FixedThreadPool : 创建固定线程数量的线程池。
  • SingleThreadExcutor: 返回只有一个线程的线程池
  • CachedThreadPool: 返回一个可根据实际情况调整线程数量的线程池。
  • ScheduledThreadPool: 返回一个用来在给定的延迟后运行任务或者定期执行任务的线程池。

线程池处理任务的流程

在这里插入图片描述

Semaphore 信号量

Semaphore(信号量)可以用来控制同时访问特定资源的线程数量。

// 初始共享资源数量
final Semaphore semaphore = new Semaphore(5);
// 获取1个许可
semaphore.acquire();
// 释放1个许可
semaphore.release();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值