线程安全-维基百科

线程安全是一个计算机编程的概念,适用于多线程编程环境。我们说一段代码是线程安全的,当它只对共享的数据进行操作,且保证它在同一时刻被多个线程安全的执行。有很多策略可以生成线程安全的数据结构。

程序可能在一个共享地址空间中创建多个线程并同步执行一段代码,在该地址空间中每个线程实际都可以访问其他线程的内存空间。

线程安全是一种属性,它通过同步来重建代码片段与控制流的关联,从而保证代码在多线程环境的运行。

目录

1.线程安全等级

2.实现方法

3.示例代码

4.参考链接


线程安全等级

软件类库可以保证线程安全。例如,并发读取可能被设计为线程安全的,但并发写入不会。使用了该类库的程序是否是线程安全,取决于它对该类库的使用是否符合其安全机制。

不同的供应商为线程安全使用稍微不同的术语。

  • 线程安全:其实现保证,当多线程访问时不需要竞争条件()
  • 有条件的线程安全:不同线程可以同步访问不同的对象,但共享数据是受竞争条件保护的。
  • 线程不安全:代码不可被不同线程同时访问。
线程安全机制通常还包含一些设计步骤来避免或减少不同形式的死锁,同时最大程度的优化并发性能。然后,防死锁并不总能保证,因为死锁可能由回调引起,或者是违反了独立于类库本身的架构层

实现方法
下面我们讨论两种方式来避开竞争条件实现线程安全。
第一类实现致力于避免使用共享状态,包括:
重入
写代码使它可以被一个线程部分执行,然后被同一个线程重新执行,或者被另一个线程同步执行时仍然能正确的完成之前的操作。这需要在变量中保存状态信息,该变量对每一次执行都是local的,通常保存在栈中,而不是静态或者全局变量或者其他非本地的状态。所有的非本地状态访问操作都必须是连续的,其数据结构必须是可重入的。
局部线程存储
变量被本地化,从而每个线程都有一份拷贝,这些变量在不同的子程序中保持自己的值,由于是本地变量所以是线程安全的,即便访问他们的代码可能被多个线程同步运行。

第二类实现和同步有关,用于共享状态不可避免的情况:
互斥现象
共享数据的访问被序列化,这种机制保证任意时刻只有一个线程对共享数据进行读写操作。互斥现象的合并需要慎重考虑,因为使用不当会引起一些副作用,如死锁,活锁和资源匮乏。
原子操作
共享数据的访问使用原子操作,原子操作不能被其他线程打断。这通常需要使用特殊的机器语言指令,该指令可能从运行时类库中获得。无论其他线程如何访问它,共享数据总是保持在一个有效的状态。原子操作构成了许多线程锁机制的基础,并被用来实现互斥现象的基本元素。
不可变对象
对象一旦被构造后,其状态不可改变。这意味着只能共享只读数据,而且它的继承类也是线程安全的。易变的/不连续的操作可以通过创建一个新的对象而不是修改已存在的对象来实现。该方法被用于Java,C#和Python的String类

示例代码:
以下Java代码中的函数是线程安全的:
class Counter {
    private int i = 0;
 
    public synchronized void inc() {
        i++;
    }
}
以下C代码片段中的函数是线程安全的,但是不可重入的:
#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被任意线程调用都没有问题,因为它使用了一个互斥元来同步所有对变量counter的访问。但是如果这个函数被用在一个可重入的中断处理程序,并且第二次中断发生在函数内,第二次中断的逻辑将永远终止。由于中断服务可以禁止其他中断,整个系统都会完蛋。

上述函数可以通过无锁元实现既是线程安全的,又是可重入的(C++ 11):
#include <atomic>
 
int increment_counter ()
{
	static std::atomic<int> counter(0);
 
	// increment is guaranteed to be done atomically
	int result = ++counter;
 
	return result;
}

参考链接
https://en.wikipedia.org/wiki/Thread_safety
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值