【线程呓语】与线程相关的一些概念
上一篇文章已经介绍了,线程是对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
【线程呓语】与线程相关的一些概念相关推荐
- 进程 线程 协程_进程 线程 协程 管程 纤程 概念对比理解
不知道是不是我自己本身就有那么一丝丝的密集恐惧,把这么一大堆看起来很相似很相关的概念放在一起,看起来是有点麻,捋一捋感觉舒服多了. 相关概念 任务.作业(Job,Task,Schedule) 在进程的 ...
- 【并行计算-CUDA开发】CUDA线程、线程块、线程束、流多处理器、流处理器、网格概念的深入理解
GPU的硬件结构,也不是具体的硬件结构,就是与CUDA相关的几个概念:thread,block,grid,warp,sp,sm. sp: 最基本的处理单元,streaming processor 最 ...
- 【Java多线程】了解线程的锁池和等待池概念
文章目录 一.内置锁 二.线程状态 线程的5种状态 线程状态图 线程释放锁的情况 线程阻塞和线程等待的区别 sleep.join.yield.wait区别 yield不释放锁案例 sleep不释放锁案 ...
- 线程的挂起是错误的概念实际是线程的阻塞,挂起只针对进程,将进程挂起会将进程从内存空间交换到磁盘空间的过程
线程的挂起是错误的概念实际是线程的阻塞 线程的主要状态有运行态,就绪态和阻塞态.挂起态对线程没有什么意义,这是由于此类状态是一个进程级的概念.特别地,如果一个进程被换出,由于它的所有线程都该进程的地址 ...
- python qthread 线程退出_线程:概念和实现
翻译:老齐 译者注:与本文相关图书推荐:<Python大学实用教程><跟老齐学Python:轻松入门> ★ 本文将分两部分刊发. " 第一部分 Python线程允许程 ...
- java线程组 线程池_JAVA多线程(三)-----线程组、线程池和线程相关类
一.线程组和未处理的异常 Thread类提供了如下几个构造器来设置新创建的线程属于哪个线程组: Thread(ThreadGroup group,Runnable target):以target的ru ...
- mysql 重启io线程_MySQL IO线程及相关参数调优
一.关于一个SQL的简单的工作过程 1.工作前提描述 1.启动MySQL,在内存中分配一个大空间innodb_buffer_pool(还有log_buffer) 2.多用户线程连接MySQL,从内存分 ...
- 线程和进程之间的联系----基本概念
什么是线程? 在回答这个问题之前先得要回答进程, 传统操作系统上进程是 pcb,操作系统通过pcb控制程序运行:但是在 linux 下线程使用 pcb 实现调度,linux下 pcb 是线程,也叫轻量 ...
- 并发编程概念、程序线程进程、线程同步、互斥量、读写锁、协程并发
多线程: 多线程就是同时执行多个应用程序,需要硬件的支持 同时执行:不是某个时间段同时,cpu切换的比较快,所有用户会感觉是在同时运行 并发与并行: 并行(parallel):指在同一时刻,有多条指令 ...
- 简述线程,程序、进程的基本概念。以及他们之间关系是什么?
1. 简述线程,程序.进程的基本概念.以及他们之间关系是什么? 线程与进程相似,但线程是一个比进程更小的执行单位.一个进程在其执行的过程中可以产生多个线程.与进程不同的是同类的多个线程共享同一 ...
最新文章
- 每天一道LeetCode-----计算给定序列中所有长度为k的滑动窗的最大值集合
- Ubuntu分别用ibus和scim安装五笔
- java jpanel 间距_Java的 . 调整JPanel上的问题大小
- spring 事务持久性_项目学生:Spring数据的持久性
- 上师大计算机学院分数线,分数低还想上师范大学?这4所师范院校,二本的分数就够了...
- 两个int()方法的区别
- LFDMM源码剖析(融入词向量的概率图模型)
- [转]HTML DIV+CSS 命名规范大全
- Android之Adobe AIR本地扩展
- Keli5 更改任意喜欢的字体
- 最美的教育最简单-净化育儿观念
- win7 安装英文语言包
- android rat工具,Android远程控制工具——AndroRat
- 云计算IaaS-Pssa-Saas(云计算的基本架构)
- 中国志愿者服务器注册,如何注册成为志愿者?中国志愿服务网注册流程
- 【转】人生如梦游戏间,RPG游戏开源开发讲座(JAVA篇)[0]——月晕础润
- apifox设置全局header
- 微信人工客服终于来了,但是「此」微信客服非「彼」微信客服
- SpringBoot安全登录验证
- LayUI导入excel功能
热门文章
- check your cluster UI to ensure that workers are registered and have sufficient resources
- springboot在intellij中的热部署(Hot swapping)配置
- No JDK found. Please validate either IDEA_JDK, JDK_HOME or JAVA_HOME
- Kaggle Kernels和 Colab, Binder, Azure Notebooks, CoCalc, Datalore的比较
- WARN HiveConf: HiveConf of name hive.metastore.local does not exist注意事项
- pandas:数据类型的转换
- anaconda 安装 pytorch
- python面试题_17道Python面试题,分享给你以防不测!
- 对node.js的net模块的一个测试
- avalon 框架