二刷多线程核心篇笔记

进程是程序向操作系统申请资源的基本单位。线程是进程中可独立执行的最小单位。

线程中调用start之前设置Daemon为true即为守护线程,否则为用户线程。

守护线程不会影响java虚拟机正常停止。用户线程会阻止java虚拟机正常停止,即全部用户线程结束之后java虚拟机才会结束。所以守护线程一般执行重要性不高的任务,比如监视情况

Thread 方法
currenThread – 返回当前执行线程
run – 由java虚拟机直接调用,而不是程序
start-- 开启一个线程,同一个线程的start不能被多次调用
join–等待线程,A线程调用B线程的join,那么A线程等待B线程结束后才执行
static yield – 主动放弃占用cpu
static sleep-- 睡眠一段时间后执行

子线程和父线程生命周期没有必然联系,父线程结束,子线程还能跑。相反也一样

线程状态
new 新建–已创建而未被调用start方法。只有一次处于这个状态(start只能被调用一次)
runnable 运行–是一个复合状态有:ready和running。前者表示线程已经准备可以被调度,后者表示线程正在运行。ready也叫作活跃线程
blocked :线程发起阻塞式io,或者申请一个其他线程持有的独占资源(比如锁)
waiting 等待:线程执行了某些操作就会处于等待其他线程执行完特定操作例如 wait,join
timed_waiting :和wait类似,不过并非等待其他线程,而是等待一个时间后自动变为runnable
terminated :线程执行完毕。只有一次处于这个状态(start只能被调用一次)

多线程优点:
提高系统吞吐量:例如一个线程因为io操作处于等待,其他线程可以执行其他
提高响应性:比如一个线程负责加载数据,一个线程负责打开界面。这样就不会导致软件界面被冻住情况
充分利用多核处理资源:
最小化对系统资源使用:多个线程可以共享所在进程所申请的资源(例如内存空间)
简化程序结构:

多线程问题:
线程安全:多个共享数据,产生数据不一致,丢失更新,脏读数据
线程活性:runnable是最好的状态。但有可能产生死锁问题。还有线程饥饿问题:某些线程永远得不到处理器执行机会。
上下文切换:处理器执行一个线程向执行另一个线程动作叫上下文切换。增加系统消耗
可靠性:某个进程突然中止例如内存泄漏导致java虚拟机奔溃,那么所在该进程的线程都会中止。

多线程编程就是把任务处理方式从串行改成并发(一段时间内交替方式完成多个任务)

竟态:计算的正确性依赖于相对时间顺序(有序性)或者线程交错(可见性)

竟态产生条件:read-modify-write(读-改-写) check-then-act(检测而后行动) 共享变量(局部变量不会)

扫描二维码关注公众号,回复: 12438012 查看本文章

arrayList HashMap SimpleDateFormat 都是非线程安全

原子操作:1.不可分割。执行线程以外任意线程看来是不可分割。所谓不可分割,指访问共享变量的操作要么执行结束,要么尚未执行。
2.或者当两个原子操作O1,O2共同访问一个共享变量时,O1执行期间(开始执行未执行结束),其他线程无法执行O2操作。这样排除了一个线程执行一个操作期间另一个线程读取或者修改该访问的共享变量导致脏读和丢失更新
3.原子操作+原子操作!=原子操作

原子操作针对共享变量而言,局部变量无所谓或者干脆看成原子操作。并且是在多线程下才有该概念。

实现原子性:使用锁(具有排他性,软件层面),使用CAS指令(硬件层面)

long和double以外任何类型变量的写操作都是原子操作。
原因:java对long/double会占用64位,而32位虚拟机对这种变量写操作分为两个步骤,比如先写低32,再写高32.

猜你喜欢

转载自blog.csdn.net/weixin_43118891/article/details/87747236
今日推荐