zoukankan      html  css  js  c++  java
  • 折返(Reentrancy)VS线程安全(Thread safety)

            在Wiki上,折返例如,下面的定义(

        In computing, a computer program or subroutine is called reentrant if it can be interrupted in the middle of its execution and then safely called again ("re-entered") before its previous invocations complete execution. The interruption could be caused by an internal action such as a jump or call, or by an external action such as a hardware interrupt or signal. Once the reentered invocation completes, the previous invocations will resume correct execution.

            翻译过来,就是说在函数运行的过程中。假设发生了中断被迫运行其他动作。其中断运行完毕后(中断运行过程中可能会再次调用该函数)。再次又一次返回函数的时候。可以恢复正确的运行过程。

            显然。定义里面并没有强调必须是多线程,并且wiki上也进一步说明了一个事实

        This definition originates from single-threaded programming environments where the flow of control could be interrupted by a hardware interrupt and transferred to an interrupt service routine (ISR). 

            简单翻译。可重入的定义是依据单线程,而且控制流能够被硬件中断打断的环境的。因此普通情况下并没有涉及和考虑到多线程的情况。


            我们再来看看线程安全的wiki定义(具体链接

        Thread safety is a computer programming concept applicable in the context of multi-threaded programs. A piece of code is thread-safe if it only manipulates shared data structures in a manner that guarantees safe execution by multiple threads at the same time. There are various strategies for making thread-safe data structures.

            简单翻译,线程安全就是保证多线程同一时候运行函数时,可以以保证安全运行的情况下操作共享数据。

    这里强调了运行的上下文必须为多线程环境。
      
            从以上两个概念的定义我们能够看到。可重入并不一定是线程安全,线程安全也并不一定是可重入的。在这里,能够举两个样例来说明

            首先,是一个可重入但不是线程安全的样例。

    下面代码段里。把局部变量s保留了全局变量t的状态,可以在中断发生之后恢复原来运行状态。符合可重入的定义。但非常明显。因为无法确保全局数据的一致性(没加锁)。因此不是线程安全

    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
    }
     
    void isr()
    {
        int x = 1, y = 2;
        swap(&x, &y);
    }
    

            然后是一个线程安全但不是可重入的样例。因为对静态变量counter的訪问之前都相互排斥锁进行同步,因此是线程安全的。但假设获取了相互排斥锁,没有释放锁的过程里。发生了中断,这时候假设在中断里再次调用函数,则会发生死锁。因此不是可重入的。

    #include <pthread.h>
     
    int increment_counter ()
    {
    	static int counter = 0;
    	static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
     
    	pthread_mutex_lock(&mutex);
     
    	// only allow one thread to increment at a time
    	++counter;
    	// store value before any other threads increment it further
    	int result = counter;	
     
    	pthread_mutex_unlock(&mutex);
     
    	return result;
    }

            由以上两个样例里,更加清晰地说明了两者之间并不一定相互决定的关系。一般来说,实现可重入要注意在函数运行过程中。假设要保存运行进度的状态,要考虑把状态保存到局部变量(栈),TLS。不能保存在全局或者静态变量,另外还要注意不能调用其他不可重入的函数。

           最后。经过在网络上的一些调查搜索,发现了部分人对可重入有第二种理解

    简单来说,就是可重入也包含多线程的情况,也就是说当单一线程在函数运行过程中。会保证当另外线程运行的正确性。

    也就是可重入包含了对单线程的重入和多线程的重入,显然后者有更强的限定性,同时也保证线程安全。

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    [ZZ]HOW TO:使用 Visual Studio .NET 将 SQL Server 2000 存储过程添加到 Visual SourceSafe
    Browsers Series_1_IE
    [ZZ]软件测试相关的63个国外站点
    常用CHM帮助文档集锦
    [ZZ]Web测试方法
    web常用的功能性测试方法
    VSTS For Testers在MSDN上的相关文章
    web测试因素
    无法解决 equal to 操作的排序规则冲突
    [ZZ]测试Web Application之三:进攻
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4740218.html
Copyright © 2011-2022 走看看