上一篇文章已经介绍了,线程是对CPU的模拟和抽象,因为一台机器只有一个CPU,又要执行多个应用的代码,为了让上层应用不考虑这些细节,而使用线程这么个东西抽象一下,这样让上层应用觉得整个CPU都是它的。但CPU毕竟只有一个(或是有限的),那么就必定存在线程的切换。这也就涉及线程的状态转换:

主意这里的箭头有双向的,有单向的。

线程在运行时可能由于需要某种资源而暂时停止运行,这称之为阻塞,当需要的资源得到满足时线程的状态会变成就绪,如果这个时候正好有CPU空闲或者正好线程调度到这个线程上,那么该线程就会马上执行。线程在运行时还有可能因为自己的时间片用完了,线程调度程序安排别的线程执行(上下文切换),而从运行状态变成就绪状态。就绪状态也可以稍后调度为运行状态。线程调度的算法有很多种,这在操作系统领域有很多文献专门来描述这个。

死锁(deadlock)

在写多线程相关的书籍或者文章中,恐怕死锁这个词出现的频率最高。那死锁到底是一个什么意思呢?

为了解释这个概念,我们假设有两个线程T1和T2,有两个资源R1和R2。在某一时刻,T1拥有R1,T2拥有R2。但是这两个线程贪得无厌,T1还需要R2才能运行所以阻塞了,而T2需要R1才能运行所以也阻塞了。所以这两个线程总是不断地尝试获取永远也得不到的东西互不相让,这种状态除非有外力的介入,不然不会打破。这就是死锁。死锁的危害性非常大,有可能造成整个系统的宕机。

我们来看下面这段程序,来演示一下如何弄出个死锁出来(该程序仅仅为了演示目的,实际中不要如此编码):

   1: using System;
   2: using System.Threading;
   3: namespace DeadLock
   4: {
   5:     class Program
   6:     {
   7:         static void Main(string[] args)
   8:         {
   9:             Test t = new Test();
  10:             Thread t1 = new Thread(t.test1);
  11:             Thread t2 = new Thread(t.test2);
  12:  
  13:             t1.Start();
  14:             t2.Start();
  15:  
  16:             Console.ReadLine();
  17:  
  18:         }
  19:     }
  20:  
  21:     public class Test
  22:     {
  23:         private object resource1 = new object();
  24:         private object resource2 = new object();
  25:  
  26:         public void test1()
  27:         {
  28:  
  29:             Console.WriteLine(string.Format("test1:Thread{0} try to get resouce1", Thread.CurrentThread.ManagedThreadId.ToString()));
  30:             lock (resource1)
  31:             {
  32:                 Console.WriteLine(string.Format("test1:Thread{0} got resouce1", Thread.CurrentThread.ManagedThreadId.ToString()));
  33:                 Thread.Sleep(500);
  34:                 Console.WriteLine(string.Format("test1:Thread{0} try to get resouce2", Thread.CurrentThread.ManagedThreadId.ToString()));
  35:                 lock (resource2)
  36:                 {
  37:                     Console.WriteLine(string.Format("test1:Thread{0} got resouce2", Thread.CurrentThread.ManagedThreadId.ToString()));
  38:                 }
  39:             }
  40:         }
  41:  
  42:         public void test2()
  43:         {
  44:             Console.WriteLine(string.Format("test2:Thread{0} try to get resouce2", Thread.CurrentThread.ManagedThreadId.ToString()));
  45:             lock (resource2)
  46:             {
  47:                 Console.WriteLine(string.Format("test2:Thread{0} got resouce2", Thread.CurrentThread.ManagedThreadId.ToString()));
  48:                 Thread.Sleep(500);
  49:                 Console.WriteLine(string.Format("test2:Thread{0} try to get resouce1", Thread.CurrentThread.ManagedThreadId.ToString()));
  50:                 lock (resource1)
  51:                 {
  52:                     Console.WriteLine(string.Format("test2:Thread{0} got resouce1", Thread.CurrentThread.ManagedThreadId.ToString()));
  53:                 }
  54:             }
  55:         }
  56:     }
  57: }

thread1获取resource1后等待一会儿,让thread2获取到resource2,然后thread1“咬住”resource1死死不放,还去获取resource2,而thread2“咬住”resource2死死不放,去获取resource1,这样thread1和thread就像抱团一样了。

死锁形成的必要条件:

互斥条件:resource1和resource2只能被一个线程拥有

占有和等待条件:已经得到resource1的thread1可以再请求resource2,thread2也可以在获取到resource2后再获取resource1

不可抢占条件:已经分配给一个线程的资源不能强制性地被抢占(thread1已经得到了resource1,不能强制地剥夺它,除非thread1自己释放resource1,在这里就是退出lock块)

循环等待条件:死锁发生时,系统中肯定有两个或两个以上的线程组成一条环路,该环路中的每个线程都等待着下一个线程已经占有的资源。

与死锁相近的一个概念是活锁,或称之为饥饿

活锁(livelock)

说的就是某个线程或进程因为某些原因总是得不到自己需要的资源。假如现在排队买饭,饭堂规定年龄小的和年龄老的可以优先买饭,站在队伍的前面,如果总是有源源不断的人加进来,且总是 比你年龄小或年龄老,你就总是排在队伍的后头,最后饥饿而死~~

还有一个常见的情况是,编程时为了提高效率,常常将写操作和读操作分开,比如多个线程可以同时读某一资源,但只要有一个线程写那么其他线程就不能读也不能写了,那么如果现在有很多线程在读资源A,而有一个线程来写,这样就会造成总是有线程在读,而写线程却插不上去。

线程安全(thread safety)

在一些框架API文档中总是会出现这么一个句子:该接口是线程安全的。那么线程安全到底是什么意思呢?

意思就是说这个接口是否能在多线程环境下安全的调用。比如该接口可能会修改一些共享的数据,而又没有对这些共享数据加锁,那么就不能安全地在多线程环境下使用了。

转载于:https://www.cnblogs.com/yuyijq/archive/2011/01/18/1938678.html

【线程呓语】与线程相关的一些概念相关推荐

  1. 进程 线程 协程_进程 线程 协程 管程 纤程 概念对比理解

    不知道是不是我自己本身就有那么一丝丝的密集恐惧,把这么一大堆看起来很相似很相关的概念放在一起,看起来是有点麻,捋一捋感觉舒服多了. 相关概念 任务.作业(Job,Task,Schedule) 在进程的 ...

  2. 【并行计算-CUDA开发】CUDA线程、线程块、线程束、流多处理器、流处理器、网格概念的深入理解

    GPU的硬件结构,也不是具体的硬件结构,就是与CUDA相关的几个概念:thread,block,grid,warp,sp,sm. sp: 最基本的处理单元,streaming processor  最 ...

  3. 【Java多线程】了解线程的锁池和等待池概念

    文章目录 一.内置锁 二.线程状态 线程的5种状态 线程状态图 线程释放锁的情况 线程阻塞和线程等待的区别 sleep.join.yield.wait区别 yield不释放锁案例 sleep不释放锁案 ...

  4. 线程的挂起是错误的概念实际是线程的阻塞,挂起只针对进程,将进程挂起会将进程从内存空间交换到磁盘空间的过程

    线程的挂起是错误的概念实际是线程的阻塞 线程的主要状态有运行态,就绪态和阻塞态.挂起态对线程没有什么意义,这是由于此类状态是一个进程级的概念.特别地,如果一个进程被换出,由于它的所有线程都该进程的地址 ...

  5. python qthread 线程退出_线程:概念和实现

    翻译:老齐 译者注:与本文相关图书推荐:<Python大学实用教程><跟老齐学Python:轻松入门> ★ 本文将分两部分刊发. " 第一部分 Python线程允许程 ...

  6. java线程组 线程池_JAVA多线程(三)-----线程组、线程池和线程相关类

    一.线程组和未处理的异常 Thread类提供了如下几个构造器来设置新创建的线程属于哪个线程组: Thread(ThreadGroup group,Runnable target):以target的ru ...

  7. mysql 重启io线程_MySQL IO线程及相关参数调优

    一.关于一个SQL的简单的工作过程 1.工作前提描述 1.启动MySQL,在内存中分配一个大空间innodb_buffer_pool(还有log_buffer) 2.多用户线程连接MySQL,从内存分 ...

  8. 线程和进程之间的联系----基本概念

    什么是线程? 在回答这个问题之前先得要回答进程, 传统操作系统上进程是 pcb,操作系统通过pcb控制程序运行:但是在 linux 下线程使用 pcb 实现调度,linux下 pcb 是线程,也叫轻量 ...

  9. 并发编程概念、程序线程进程、线程同步、互斥量、读写锁、协程并发

    多线程: 多线程就是同时执行多个应用程序,需要硬件的支持 同时执行:不是某个时间段同时,cpu切换的比较快,所有用户会感觉是在同时运行 并发与并行: 并行(parallel):指在同一时刻,有多条指令 ...

  10. 简述线程,程序、进程的基本概念。以及他们之间关系是什么?

    1. 简述线程,程序.进程的基本概念.以及他们之间关系是什么?     线程与进程相似,但线程是一个比进程更小的执行单位.一个进程在其执行的过程中可以产生多个线程.与进程不同的是同类的多个线程共享同一 ...

最新文章

  1. 每天一道LeetCode-----计算给定序列中所有长度为k的滑动窗的最大值集合
  2. Ubuntu分别用ibus和scim安装五笔
  3. java jpanel 间距_Java的 . 调整JPanel上的问题大小
  4. spring 事务持久性_项目学生:Spring数据的持久性
  5. 上师大计算机学院分数线,分数低还想上师范大学?这4所师范院校,二本的分数就够了...
  6. 两个int()方法的区别
  7. LFDMM源码剖析(融入词向量的概率图模型)
  8. [转]HTML DIV+CSS 命名规范大全
  9. Android之Adobe AIR本地扩展
  10. Keli5 更改任意喜欢的字体
  11. 最美的教育最简单-净化育儿观念
  12. win7 安装英文语言包
  13. android rat工具,Android远程控制工具——AndroRat
  14. 云计算IaaS-Pssa-Saas(云计算的基本架构)
  15. 中国志愿者服务器注册,如何注册成为志愿者?中国志愿服务网注册流程
  16. 【转】人生如梦游戏间,RPG游戏开源开发讲座(JAVA篇)[0]——月晕础润
  17. apifox设置全局header
  18. 微信人工客服终于来了,但是「此」微信客服非「彼」微信客服
  19. SpringBoot安全登录验证
  20. LayUI导入excel功能

热门文章

  1. check your cluster UI to ensure that workers are registered and have sufficient resources
  2. springboot在intellij中的热部署(Hot swapping)配置
  3. No JDK found. Please validate either IDEA_JDK, JDK_HOME or JAVA_HOME
  4. Kaggle Kernels和 Colab, Binder, Azure Notebooks, CoCalc, Datalore的比较
  5. WARN HiveConf: HiveConf of name hive.metastore.local does not exist注意事项
  6. pandas:数据类型的转换
  7. anaconda 安装 pytorch
  8. python面试题_17道Python面试题,分享给你以防不测!
  9. 对node.js的net模块的一个测试
  10. avalon 框架