线程安全与可重入函数

1.线程安全

线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据

【概述】

如果代码所在的进程中右多个进程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他变量的值和也和预期得而是一样的,就是线程安全的。若有多个线程同时写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

线程安全问题都是有全局变量和静态变量引起的。

若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的。

2.可重入

在多线程或有异常控制流的情况下,当某个函数运行到中途时,控制流有可能被打断去执行另一个函数,而这”另一个函数”有可能是他本身,如果在这种情况下不会出现问题,比如与说数据或状态不被破坏,而且行为可预期,那么这个函数就被称为可重入的。反之,就是不可重入函数 。

简单来说就是:当一个函数被多个线程调用的时候,不会引用任何共享数据,那么这个函数就是可重入的。可重入函数可以在任意时刻被中断,稍后再继续运行,也不会丢失数据。反之就是不可重入。

可重入函数也可以这样理解,重入即表示重复进入,首先它意味着这个函数可以被中断,其次意味着它除了使用自己栈上的变量以外不依赖于任何环境(包括static),这样的函数就是purecode(纯代码)可重入,可以允许有多个该函数的副本在运行,由于它们使用的是分离的栈,所以不会互相干扰。如果确实需要访问全局变量(包括static),一定要注意实施互斥手段。可重入函数在并行运行环境中非常重要,但是一般要为访问全局变量付出一些性能代价。

保证函数的可重入性的方法

在写函数时候尽量使用局部变量(例如寄存器、堆栈中的变量),对于要使用的全局变量要加以保护(如采取关中断、信号量等方法),这样构成的函数就一定是一个可重入的函数。

VxWorks中采取的可重入的技术有:
* 动态堆栈变量(各子函数有自己独立的堆栈空间)
* 受保护的全局变量和静态变量
* 任务变量

3.线程安全与可重入的区别于联系

线程安全的根源就在于”共享数据”。所以不共享任何数据的函数(可重入函数)肯定是线程安全的。但是,即使有共享数据,线程安全还可以通过同步与互斥来保证,所以线程安全并不一定是可重入的。
可重入是线程安全的一个真子集,可重入一定线程安全,但线程安全不一定可重入。

4.怎样编写可重入函数

关于线程安全,我们可以通过同步与互斥来实现,下面介绍一下编写可重入函数时的规范:

1、不能在函数内部使用静态或全局数据
2、不能返回静态或全局数据,所有数据都有函数的调用者提供
3、使用本地数据、或通过制作全局数据的本地拷贝来保护全局数据。
4、如果必须访问全局变量,利用互斥机制来保护全局变量。
5、不在可重入函数内部调用不可重入函数。、
6、不调用malloc和free函数,因为malloc是用全局链表来管理堆的。
7、不调用了标准I/O函数。标准I/O函数很多都以不可重入的方式实现全局数据结构。

总结:最常见的就是在信号处理函数中不能使用不可重入函数。如果在信号处理函数中使用了不可重入函数,则可能导致程序出现错误甚至崩溃。

博客参考:
http://blog.youkuaiyun.com/lf_2016/article/details/56928552
http://www.1024do.com/?p=4135#comment-76

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值