【Linux】线程安全和可重入函数

线程安全

所谓线程安全,就是当多个线程访问同一个数据时,不会造成数据出错。其实它是采用了加锁的机制来保证在一个线程访问该数据时,其他的线程不可以访问,直到等到那个线程访问结束才可以访问。而线程不安全,就是没有采用加锁的机制来保证这一点。

测试代码

#include<stdio.h>
#include<pthread.h>

int g_count = 0;

void* threadCount(void* arg)
{
	int tmp = 0;
	int count = 0;
	while(count < 5000)
	{
		tmp = g_count;
		printf("线程ID : %u , g_count : %d\n",pthread_self(),g_count);//打印线程自己的ID,以及当前的g_count值
		g_count = tmp+1;
		count ++;
	}
}

int main()
{
	pthread_t thread1,thread2;//声明线程变量

	pthread_create(&thread1, NULL , threadCount,NULL);//创建线程
	pthread_create(&thread2, NULL , threadCount,NULL);

	pthread_join(thread1,NULL);//以阻塞的方式等待线程的终止
	pthread_join(thread2,NULL);//以阻塞的方式等待线程的终止
	return 0;
}

运行结果

第一次运行结果


第二次运行结果


我们发现每次的运行结果都不大一样

分析

造成线程安全的程序都是由于全局变量以及静态变量引起的

解决方法

利用互斥锁来实现互斥

四类不是线程安全的函数

(1)不保护共享变量的函数。

(2)函数状态随着调用而改变的函数

(3)返回静态指针变量的函数

(4)调用非线程安全的函数

可重入函数

概念

重入

当函数被不同的控制流程调用时,有可能在一次调用没有返回时,另一个控制流程又重新进入该函数,这种现象称之为重入

不可重入函数

当发生重入现象后,程序逻辑有可能会发生错乱。这类函数成为不可重入函数。

可重入函数

当发生重入现象后,程序逻辑不会错乱。

哪些函数是一定不可重入

1. 调用malloc或free,因为malloc也是用全局链表来管理堆的。 

2. 调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的⽅式使用全局数据结构。

3. SUS规定有些系统函数必须以线程安全的方式实现。

测试代码

#include<stdio.h>

int flag = 0;

void myhandler(int signal)
{
	flag = 1;
	printf("falg = %d\n",flag);
}

int main()
{
	signal(2,myhandler);

	printf("proc start!\n");
	while(!flag);
	printf("proc end!\n");
	return 0;
}

运行结果


接下来我们使用 -O3选项来让编译器进行优化

优化后的运行结果如下


进过编译器优化后,全局变量的flag保存在寄存器中

而myhandler函数中的flag保存在内存中,此时发送信号改变的是内存中的flag值

而寄存器中的flag仍为0,所以程序仍会运行。

现在我们加入volatile 关键字

运行结果如下


程序又正常运行了

线程安全和可重入函数的区别

1.线程安全是在多线程情况下发生,可重入函数在只有一个线程的情况下发生。 

2.线程安全不一定是可重入的,而可重入函数则一定是线程安全的。 

3.一个函数有全局变量,则这个函数既不是线程安全也不是可重入的;一个函数当中的数据全身自身栈空间的,则这个函数即使线程安全也是可重入的。 

4.对临界资源的访问加锁,则函数是线程安全的;但如果重入函数的话加锁还未释放,则会产生死锁,因此不能重入。 

5.线程安全函数能够使不同的线程访问同一块地址空间,而可重入函数要求不同的执行流对数据的操作不影响结果,使结果是相同且正确。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值