多线程编程离不开锁,可加锁会引起性能,甚至是死锁,那到底什么是多线程安全的?
1.局部变量局部使用是安全的
每个thread 都有自己的运行堆栈,而局部变量是生存在堆栈中,大家不干扰。
{int local1;
++local1;} 是安全的
2.在32机器上,4字节整形一次assign是原子的
比如
i =10; //thread1
i=4; //thread2
不会导致i的值处于未知状态,要么是10要么是4
3.全局原生变量多线程读写是不安全的
++global2; //! InterlockedIncrement保证整型变量自增的原子性
++这个操作其实分为两部,一个是读,另外一个是写
mov ecx,global
add ecx,1
mov global,ecx
全局原生变量多线程读写也不一定是不安全的,比如
假设 struct T
T* global_t;
T* nt = new T;
T* temp = & global_t;
do{
memcpy(nt, global_t, sizeof(T));
//修改
}while(!CAS(&global_t, temp, nt)); CAS 可以用 xchgcmp 指令来实现
4.volatile不能保证全局整形变量是多线程安全的么
volatile仅仅是告诫compiler不要对这个变量作优化,每次都要从memory取数值,而不是从register
5.function static object的初始化不是多线程安全的
著名的Meyer Singleton其实不是线程安全的
Object & getInstance()
{
static Object o;
return o;
}
可能会造成多次初始化对象
写好多线程安全的法宝就是封装,使数据有保护的被访问到
安全性:局部变量>成员变量>全局变量