java 并发基础-线程介绍

138 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

并发的基础就是多线程,我们先来了解线程的相关状态

在Thread中有一个枚举类,列举了线程的6个状态.

其实应该是7种状态,少了一个就绪状态,,Java直接将就绪和运行中归为一类

v2-326a2be9b86b1446d75b6f52f54c98fb_1440w.jpg

 public enum State {
         // 创建状态 : 尚未启动的线程
         NEW,
 ​
         // 运行状态 : 包括就绪状态READY和运行状态RUNNING
         RUNNABLE,
 ​
         // 阻塞状态 : 线程等待锁,线程正在等待获取锁去进入同步方法/同步块
   //   只有synchronized修饰的才能进入BLOCKED状态
         BLOCKED,
 ​
         /**
         *等待状态: 
         不指定超时时间的等待方法
         wait,join,park ,这些方法会被
         **/
         WAITING,
 ​
         /**
          * 超时等待状态:
          指定超时时间的等待方法.
          包括sleep,wait,parkNanos,join等
          **/
         TIMED_WAITING,
 ​
         // 中止状态 : 
   // 任务执行完 异常退出
         TERMINATED;
    }

注意点:

1.只有synchronized修饰的才能进入BLOCKED状态 :

LOCK为什么不行:LOCK的底层是AQS,依赖park,LOCK 在同步队列中使用的park,状态变成了WAITING,没有BLOCKED状态

2.将操作系统的READYRUNNING状态合并到了RUNNABLE

3.触发WAITING状态的动作都是需要唤醒(手动或者隐式) 的.唤醒方法即从WAITING -> RUNNABLE

wait,join,park 这些方法都是有唤醒条件的.因此

4.BLOCKEDWAITING关系

在sync或者lock中,我们有两个队列,一个是同步队列,一个是等待队列,可以与两个状态对应.

Synchronized当调用wait/方法时,线程会进入等待队列,状态变成WAITING,唤醒进入同步队列,等待获取锁,状态变成BLOCKED.当获取成功,再变成RUNNABLE.BLOCK相当于WAITING的后续处理,WAITING与RUNNABLE的中间人

wait/notify

Object的方法

wait和notify需要获得锁,即在sync代码块中使用。当notify执行完毕才会去唤醒wait

线程竞争获取锁后才能在wait()处返回

线程执行wait之后会进入等待队列,当被notify通知后就会进入同步队列来竞争锁。

image-20220308001348338.png

sleep/yield

两个都是Thread的方法

sleep是让当前线程休眠,主动让出CPU调度。从运行态变成阻塞状态(其他阻塞)。

sleep不会释放同步资源锁,因此超时后会进入就绪状态

yield是让步,让线程从运行态变成就绪状态,尽量让其他就绪态的线程获得调度,但是不保证

sleep(0) 和 yield() 的作用一样,都是将CPU执行权让出

park

Unsafe.park() 调用本地方法的park可以执行挂起操作

Unsafe.unpark() park的许可,从挂起返回.

unpark可以在park之前,相当于一一抵消.但是如果操作再unpark之前,park之后就会形成死锁