线程 重入

可重入函数:

    简单说就是可以被中断,并且最终仍可以得到正确结果的函数。

当一个执行流因为异常或者被内核切换而中断当前正在执行的函数X去执行另外一个执行流,后者的执行 

流并不影响前一个执行流中断恢复后执行函数X产生的结果,就称这个函数为可重入函数

一个可重入函数需要满足的是:

1、不使用全局变量或 static静态变量;//如使用全局变量必须对全局变量加以保护才可以是重入
        2、不使用用malloc或者new开辟出的空间;
        3、不调用不可重入函数;
        4、不返回静态或全局数据,所有数据都有函数的调用者提供;
        5、使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据;

注意:

当函数一些参数是引用传递(使用了指针),应该小心地传递指向共享数据的指针//???????????

可重入函数可以允许有该函数的多个副本在运行,由于它们使用的是分离的栈,所以不会互相干扰。如果确实需要

访问全局变量(包括static),一定要注意实施互斥手段。编写可重入函数时,则应通过关中断、信号量(即P、V操

)等手段对其加以保护。

以下函数是异步信号安全版本(可重入函数)但不是线程安全函数


int t; 
void swap(int *x, int *y) 
{ 
    int s; 
    s = t; // save global variable 
    t = *x; 
    *x = *y; // hardware interrupt might invoke isr() here! 
    *y = t; 
    t = s; // restore global variable 
} 

分析:

中断、信号处理函数中调用时,每次使用t之前都会进行备份,返回之前还原t的值;所以是可重入函数

如用在线程中,则有可能线程切换之前未来得及还原t的值,导致结果出错,所以在线程中是不可重入的 

也就不是线程安全函数

线程安全函数:

当被多个并发线反复调用时,它会一直产生正确的结果的函数(不用考虑同步的问题)

线程安全函数符号:  _POSIX_THREAD_SAFE_FUNCTIONS (在<unistd.h> 中定义)

四类函数称为线程不安全的

1、不保护共享变量的函数;
      2、函数状态随着调用改变的函数;
      3、返回指向静态变量指针的函数;
      4、调用线程不安全函数的函数;

很多函数并不是线程安全的,因为他们返回的数据是存放在静态的内存缓冲区中的。通过修改接口,由调用者自行提供缓冲区就可以使这些函数变为线程安全的。

gethostbyname()是线程不安全的,在Linux中提供了gethostbyname_r()的线程安全实现。

 

可重入函数与线程安全的区别与联系

函数可以是可重入的,也可以是线程安全的,或者两者皆是,或者两者皆非。不可重入函数不能由多个线程使用。

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

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

3、如果一个函数有全局变量,则这个函数既不是线程安全也不是可重入的。

4、如果一个函数当中的数据全身自身栈空间的,则这个函数即使线程安全也是可重入的。

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

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

 

多线程程序中常见的疏忽性问题

· 将指针作为新线程的参数传递给调用方栈,

· 在没有同步机制保护的情况下访问全局内存的共享可更改状态。

· 两个线程尝试轮流获取对同一对全局资源的权限时导致死锁。其中一个线程控制第一种资源,另一个线程控制第二种资源。其中一个线程放弃之前,任何一个线程都无法继续操作。

· 尝试重新获取已持有的锁(递归死锁)。

· 在同步保护中创建隐藏的间隔。如果受保护的代码段包含的函数释放了同步机制,而又在返回调用方之前重新获取了该同步机制,则将在保护中出现此间隔。结果具有误导性。对于调用方,表面上看全局数据已受到保护,而实际上未受到保护。

· UNIX 信号与线程混合时,使用sigwait(2) 模型来处理异步信号。

· 调用setjmp(3C) 和longjmp(3C),然后长时间跳跃,而不释放互斥锁。

· 从对*_cond_wait() 或*_cond_timedwait() 的调用中返回后无法重新评估条件。

 

参考:

        http://blog.youkuaiyun.com/u012317833/article/details/39546377;

        http://blog.youkuaiyun.com/lidonghat/article/details/52881418;

http://blog.youkuaiyun.com/yang8518296/article/details/11845073;

http://blog.youkuaiyun.com/scenlyf/article/details/52074444;



<think>好的,用户想了解多线程编程中的重入概念及其定义和作用。首先,我需要回忆一下重入的基本定义。重入(Reentrancy)在编程中通常指的是函数或代码段在未执行完的情况下被再次调用的能力。这在多线程环境中尤其重要,因为多个线程可能会同时调用同一段代码。 接下来,我得区分可重入函数和不可重入函数可重入函数的关键在于它们不依赖静态数据、全局变量或者不可重入函数,这样即使被多个线程同时调用,也不会出现数据竞争或不一致的情况。而不可重入函数可能使用了共享资源,比如全局变量,导致线程不安全。 然后,用户可能需要知道为什么重入性重要。比如,在多线程环境中,如果一个函数是不可重入的,多个线程同时调用它可能导致数据错误或程序崩溃。所以,确保函数可重入性是编写线程安全代码的重要部分。 不过,我得注意不要混淆重入线程安全这两个概念。虽然它们相关,但线程安全的范围更广,可能通过同步机制(如互斥锁)来实现,而可重入性更强调不依赖共享状态,无需同步也能安全执行。 用户提供的引用资料中提到了多线程编程的细节问题,这可能包括如何设计可重入函数以及常见的陷阱。比如,引用[2]提到为C++初学者提供参考,可能需要更详细地解释如何避免使用全局变量,或者如何管理局部数据。 另外,用户可能对实际例子感兴趣,比如可重入函数和不可重入函数的对比。例如,使用静态变量的函数通常是不可重入的,而只使用局部变量和参数的函数可能是可重入的。 最后,需要确保回答结构清晰,分点说明定义、作用、应用场景以及如何实现,这样用户能逐步理解。同时,生成的相关问题应该覆盖常见的疑问,比如如何判断函数是否可重入,或者如何将不可重入函数改造为可重入的。</think>### 多线程编程中的重入(Reentrancy) #### 定义 **重入**指在多线程或中断驱动的环境中,某个函数或代码段在未执行完毕时被再次调用,仍能正确执行的能力[^2]。 - **可重入函数**:不依赖全局变量、静态数据或不可重入资源,仅通过局部变量和参数完成逻辑,可被多个线程同时调用而不会产生冲突。 - **不可重入函数**:依赖共享资源(如全局变量、静态存储区、硬件设备等),在多线程并发调用时可能导致数据不一致或逻辑错误。 #### 作用 1. **线程安全**:可重入函数天然支持多线程并发,无需额外同步机制(如互斥锁)。 2. **减少资源竞争**:避免因共享资源冲突导致的死锁或性能下降。 3. **提高可靠性**:在中断处理、信号处理等场景中,重入能力确保代码在异步调用下的正确性。 #### 实现可重入性的条件 | 特征 | 可重入函数 | 不可重入函数 | |---------------------|---------------------|-----------------------| | 依赖全局变量/静态数据 | ❌ | ✔️ | | 调用不可重入函数 | ❌ | ✔️ | | 使用动态分配内存 | ✔️(需独立管理) | ✔️(可能共享) | | 线程间独立状态 | ✔️ | ❌ | #### 示例对比 ```c++ // 不可重入函数:依赖静态变量 int non_reentrant() { static int counter = 0; // 静态变量导致线程不安全 return counter++; } // 可重入函数:仅使用参数和局部变量 int reentrant(int* counter) { (*counter)++; // 状态由调用方管理 return *counter; } ``` #### 应用场景 - **信号处理函数**:需保证异步调用时能安全执行[^2]。 - **线程池任务**:多个线程并行处理相同逻辑时依赖可重入代码。 - **递归算法**:递归调用本质上是单线程内的“重入”,但需注意资源隔离。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值