1线程同步-底层支持
来源:互联网 发布:义隆单片机 编辑:程序博客网 时间:2024/05/22 12:22
并发错误
多线程带来效率的提高,但是也带来了对原子操作的破坏。
例如
C代码
汇编代码
i++;
mov eax,[i]
inc eax
mov [i],eax
假设i=0; 两个线程执行后应该为2;
如果按照如下方式执行结果为1
线程1
线程2
mov eax,[i];
等待
等待
mov eax,[i];
等待
Inc eax;
等待
mov [i],eax;
inc eax;
等待
mov [i],eax;
等待
原子操作
如果是单处理器使用一条指令完成即可实现原子操作Inc [i];
如果是多处理器inc[i]; 依然不是原子的;使用lock 指令前缀锁定内存后才能保证指令的原子性 lock inc [i];
自旋锁中的原子操作
从上面可以看出,对数据的原子操作,直接是硬件支持的,如果操作的数据比较复杂要实现对这个复杂数据的原子操作就需要硬件和软件一起配合来完成。具体方法如下:
设有变量l 为0表示已经加锁,1 表示未加锁
加锁代码如下:
1: lock decb [l]
jns 3
2: rep nop
cmpb 0, [l]
jle 2
jmp 1
3: ….(排它性操作代码操作)
Lock incb [l]
如果未加锁:的执行路径为: 执行完1 跳转到3继续执行后面的逻辑。
如果已经加锁的 执行路径为:执行完1,因跳转条件不成立,就执行2,并在2中不停的循环检查,直到锁释放(l为1)跳转到1重新执行,直到具备执行3中的逻辑,这样就保证了3中代码的原子性,在3中可以执行复杂的数据操作。
信号量中的原子操作
设有信号量sc初始为0。
申请操作如下:
Lock decl [sc] // 对信号量减1操作
Js 2 // 信号量小于0
1: ….(申请成功执行的代码)
2: lea eax, [sc] //
Call 申请信号量失败函数 //(进入内核态睡眠,有信号量从内核态返回)
Jmp 1 //
释放操作如下:
Lock incl [sc] // 对信号量加1操作
Jle 2 //小于有需要唤醒的线程
1: 信号量释放成功的代码逻辑
2: lea eax, [sc]
Call 唤醒阻塞的线程(进入内核态)
Jmp 1
- 1线程同步-底层支持
- java线程同步锁优化--底层虚拟机
- 线程同步1
- Java线程同步 1
- JAVA线程同步(1)
- 同步线程1(lock)
- 线程同步1-synchronized
- 线程同步1 ------ 互斥锁
- 底层工具库支持
- 线程同步--线程同步--线程同步--线程同步--线程同步
- C#线程同步(1)-------轻量级同步Interlock
- 深入浅出:线程底层原理
- 线程也疯狂----线程同步(1)
- 线程也疯狂----线程同步(1)
- 线程也疯狂----线程同步(1)
- 线程也疯狂----线程同步(1)
- 线程同步(1) - 用户模式下的线程同步
- 线程同步(1) - 用户模式下的线程同步
- CString、CStringA 和 CStringW
- postgresql数据库存储过程、索引、触发器相关SQL梳理
- android开发之MediaPlayer+Service MP3播放器
- Charles 从入门到精通
- kafka系列(七)使用Kafka-Connect导入导出数据
- 1线程同步-底层支持
- TODO-3:css relative and absolute
- 利用link标签rel="alternate stylesheet"属性实现界面动态换肤
- iOS-破解版PS
- Mac OS X 10.12.1下安装Homebrew
- Android官方开发文档Training系列课程中文版:Activity测试之创建功能性测试
- JSP四个作用域
- Android App支付:支付宝SDK接入详细指南(附官方支付demo)
- 面向对象的三个基本特征摘要