线程 重入

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014325402/article/details/78314601

可重入函数:

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

当一个执行流因为异常或者被内核切换而中断当前正在执行的函数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.csdn.net/u012317833/article/details/39546377;

        http://blog.csdn.net/lidonghat/article/details/52881418;

http://blog.csdn.net/yang8518296/article/details/11845073;

http://blog.csdn.net/scenlyf/article/details/52074444;



没有更多推荐了,返回首页