可重入与线程安全
概念
- 线程安全函数:函数可以同时被多个线程调用,并安全访问共享数据(各个线程有序访问)。
- 可重入函数:函数可以同时被多个线程调用,但每个线程只能使用各自的数据。
- 线程安全的类:每个线程使用这个类的相同的实例,成员函数也可以被每线程安全调用。
- 可重入的类:每个线程使用这个类的不同的实例,成员函数就可以被每线程安全调用。
可重入性
class Counter
{
public:
Counter() { n = 0; }
void increment() { ++n; }
void decrement() { --n; }
int value() const { return n; }
private:
int n;
};
Counter类是可重入,但不是线程安全的。
因为++和–操作符不是原子性的,它们通常要经历以下三个步骤:
- 寄存器读取内存中变量的值
- 增加或减少寄存器的值
- 将寄存器写回内存
如果线程B在线程A将值写回内存前调用相同的++操作符,那么最终变量只会增加1。
线程安全
class Counter
{
public:
Counter() { n = 0; }
void increment() {locke(&mutex); ++n; unlocke(&mutex)}
void decrement() {locke(&mutex); --n; unlocke(&mutex)}
private:
int n;
};
lock和unlock是原子性的,使用锁机制,令共享数据被多个线程有序地访问,从而保证了线程安全性。