操作系统(2)进程、线程、锁

举报
用户已注销 发表于 2021/11/19 00:00:36 2021/11/19
1.5k+ 0 0
【摘要】 目录 1,进程和线程 2,线程调度 3,Linux系统的进程和线程 4,原子操作、同步、锁 5,可重入 6,过度优化 VS 线程安全 1,进程和线程 每个进程都有自己的独立内存空间。 线程,也可以成为轻量级进程,一个进程由一个到多个线程组成。 2,线程调度 CPU的运行被切割成时间片,每个时间片运行...

目录

1,进程和线程

2,线程调度

3,Linux系统的进程和线程

4,原子操作、同步、锁

5,可重入

6,过度优化 VS 线程安全


1,进程和线程

每个进程都有自己的独立内存空间。

线程,也可以成为轻量级进程,一个进程由一个到多个线程组成。

2,线程调度

CPU的运行被切割成时间片,每个时间片运行一个线程,不断切换运行线程。

线程至少有3个状态:运行running、就绪ready、等待waiting

3,Linux系统的进程和线程

4,原子操作、同步、锁

一个独立的不被其他操作影响的操作叫原子操作。

线程是共享数据的,为了避免同时读写导致数据异常,需要对数据进行访问同步,即一个线程访问的时候另外一个线程不能访问,这样的访问就是原子操作。

同步的最常见方法就是锁。

常见的锁:信号量、互斥量、临界区、读写锁、条件变量

5,可重入

函数重入

函数可重入指的是,该函数重入之后,不会产生任何不良后果。

可重入函数的特点:

6,过度优化 VS 线程安全

(1)一些复杂的优化行为,会让锁失效。

案例一:将变量写入寄存器而不写回

编译器为了提高访问速度,将变量x写入寄存器而不写回,可能导致最终x的值是1,本来应该是2的。

案例二:交换指令顺序

编译器可能会为了提高效率而交换相邻两条无关指令的顺序,CPU的动态调度功能也会交换指令执行的顺序。

这样,最终结果可能就是r1=r2=0,本来是不可能这样的。

(2)使用volatile关键字,可以阻止编译器为了提高访问速度,将变量x写入寄存器而不写回,可以阻止编译器操作volatile变量的指令顺序。

所以,volatile可以解决案例一,但是无法解决案例二,因为CPU有动态调度。

(3)单例模式的double-check

案例三:还是交换指令顺序

这个是单例模式,申请一个对象,双重if判断是为了降低lock的调用,提高效率。

而(2)(3)的顺序是可以颠倒的,所以如果函数并发调用,就会有一个正在调用构造函数的对象的指针,被提供给调用方,从而引发错误。

CPU通常会提供一条屏障指令,用来组织指令交换顺序的时候穿过屏障,有的叫barrier,有的叫lwsync

例如,可以这样来解决上面的问题:

文章来源: blog.csdn.net,作者:csuzhucong,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nameofcsdn/article/details/120319751

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。