线程安全

转自线程安全


线程安全是编程中的术语,指某个函数 (计算机科学)、函数库在多线程环境中被调用时,能够正确地处理各个线程的局部变量,使程序功能正确完成。

一般来说,线程安全的函数应该为每个调用它的线程分配专门的空间,来储存需要单独保存的状态(如果需要的话),不依赖于“线程惯性”,把多个线程共享的变量正确对待(如,通知编译器该变量为“易失(volatile)”型,阻止其进行一些不恰当的优化),而且,线程安全的函数一般不应该修改全局对象。

很多C库代码(比如某些strtok的实现,它将“多次调用中需要保持不变的状态”储存在静态变量中,导致不恰当的共享)不是线程安全的,在多线程环境中调用这些函数时,要进行特别的预防措施,或者寻找别的替代方案。

例子

在下面这段代码中,函数increment_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;
}

上面的代码中,函数increment_counter可以在多个线程中被调用,因为有一个互斥锁mutex来同步对共享变量counter的访问。但是如果这个函数用在可重入的中断处理程序中,如果在pthread_mutex_lock(&mutex)和pthread_mutex_unlock(&mutex)之间产生另一个调用函数increment_counter的中断,则会第二次执行此函数,此时由于mutex已被lock,函数会在pthread_mutex_lock(&mutex)处阻塞,并且由于mutex没有机会被unlock,阻塞会永远持续下去。

使用c++11中的atomics,可使此函数即线程安全又可重入。

#include <atomic>
 
int increment_counter ()
{
	static std::atomic<int> counter(0);
 
	// increment is guaranteed to be done atomically
	int result = ++counter;
 
	return result;
}


原文地址:https://www.cnblogs.com/noble/p/4144111.html