操作系统之线程状态图

本文主要介绍了线程的状态图,以及通过iOS中NSThead的具体例子来详细解释每个状态的意义。

  • 线程状态图综述
  • JAVA中线程状态图实例
  • iOS中NSThead线程状态图

线程状态图综述

  1. 新建状态(New) : 线程对象被创建后,就进入了新建状态。

  2. 就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程

  3. 运行状态(Running) : 线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。

  4. 阻塞状态(Blocked) : 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

    等待阻塞 – 通过调用线程的wait()方法,让线程等待某工作的完成。
    同步阻塞 – 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
    其他阻塞 – 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

  5. 死亡状态(Dead) : 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

下面通过一个更具体的运行图来再次解释线程的各个状态

JAVA中线程状态图实例

img

详细解释三种阻塞状态

(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。

(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。

(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

补充:

Synchronized是非公平锁。 Synchronized在进入等待列表时,等待的线程会先尝试自旋获取锁,如果获取不到就进入等待列表,这明显对于已经进入队列的线程是不公平的。

iOS中NSThead线程状态图

下面是iOS中NSThead的使用详解

新建状态 : 实例化线程对象

1
2
3
4
说明:创建线程有多种方式,这里不做过多的介绍
NSThread *thread =[[NSThread alloc] initWithTarget:self
selector:@selector(run)
object:nil];

就绪状态 :向线程对象发送 start 消息,detachNewThreadSelector 方法和 performSelectorInBackground 方法会直接实例化一个线程对象并加入可调度线程池

1
2
线程开启 : 线程进入可调度线程池
[thread start];

运行状态:

  • CPU 负责调度可调度线程池中线程的执行
  • 线程执行完成之前(死亡之前),状态可能会在就绪和运行之间来回切换
  • 就绪和运行之间的状态变化由 CPU 负责,程序员不能干预

img

  • 当 CPU 调度当前线程 , 进入运行状态
  • 当 CPU 调度其他线程 , 进入就绪状态

阻塞状态 : 当满足某个预定条件时,可以使用休眠或锁阻塞线程执行

1
2
3
4
5
方法执行过程,符合某一条件时,可以利用 sleep 方法让线程进入 阻塞 状态

sleepForTimeInterval: //休眠指定时长 (从现在起睡多少秒)
sleepUntilDate: //休眠到指定日期 (从现在起睡到指定的日期)
@synchronized(self) { } //互斥锁

死亡状态: (一旦线程停止或死亡了,就不能再次开启任务 , 后续的所有代码都不会被执行 )

1
2
(1) 正常死亡
- 线程执行完毕
1
2
3
4
(2) 非正常死亡
- [NSThread exit](自杀) 当满足某个条件后,在线程内部自己中止执行
- (被逼着死亡) 当满足某个条件后,在主线程给其它线程打个死亡标记,让子线程自行了断.
注意:在终止线程之前,应该注意释放之前分配的对象!

内存情况 : 线程死亡后,线程对象从内存中移除