最开始知道这个内容是在和室友聊天的时候发现的,它说国内某互联网公司中有一道笔试题,需要当场写出无锁队列的代码。当时对于这个概念还是一知半解,后来他说陈皓博客上有相关的内容,本着好学的精神就去一窥究竟:无锁队列的实现
基本思想是利用编译器或者语言提供的原子操作,CAS(compare and swap或者compare and set)。
bool compare-and-swap(Adderss addr, Value old, Value new)
{
if (*addr = old) {
*addr = new;
return true;
}
return false;
}
其实原子操作是因为并行编程的问题而更加受到重视。因为在传统的单核CPU上,在同一时刻只有一个线程(或者进程)在运行。不同线程之间不会产生竞争,也就不就引入所谓的锁或者其他保证在临界区的互斥访问。
在多线程的环境下对于资源的分配需要给予足够的重视,一方面变量被重复初始化或者造成资源的丢失。在单例模式中:
class Singleton
{
public:
static Singleton *instance (void)
{
if (instance_ == 0)
// critical section
instance_ = new Singleton;
return instance_;
}
void method(void);
private:
static Singleton *instance_;
};
在上面的critical section标记中,当多个线程同时到达这个地方时,instance_可能会被多次初始化。
简单直接的解决方法即枷锁
class Singleton
{
public:
static Singleton *instacne(void)
{
// Constructor of guard acquires
// lock_ automatically
Guard<Mutex> guard (lock_);
// only one thread in the
// critical section in a time
if (instance_ == 0)
instance_ = new Singleton;
return instance_;
}
private:
static Mutex lock_;
static Singleton *instance_;
};
简单粗暴的加锁方式使得访问instance的效率大大降低,即使是访问instance_也需要获得锁。Schmidt等人提出一种Double checked locking方式,如下:
class Singleton
{
public:
static Singleton *instacne(void)
{
// first check
if (instance_ == 0)
{
Guard<Mutex> guard (lock_);
if (instance_ == 0)
instance_ = new Singleton;
// only one thread in the
// critical section in a time
}
return instance_;
}
private:
static Mutex lock_;
static Singleton *instance_;
};
这种双加锁的方式具有一定的应用场景,但是也不是万能的。看一段Java的利用double checked locking的代码:
public void addResult(String uri, ProfilerData data)
{
Long key = new Long(data.getKey(uri));
// critical section
ProfilerResult result = (ProfilerResult)results.get(key);
if (result == null)
{
synchronized(results)
{
if ((result == (ProfilerResult)results.get(key)) == null)
results.put(key,result = new ProfilerResult(uri, RESULTS_COUNT));
}
}
results.addData(data);
}
注意上述表明的critical section区域。这句话不是同步的,则后面的判断就会出错。所以经典的方法在使用时必须注意实际的应用性。关于并行程序最好是使用公开的算法,因为一般都受过检验。
本文完
参考:
[1] Schmidt等 double checked locking
[2] Code quality
[3] C++ concurrency in action, Jolt奖的书