最開始知道這個內容是在和室友聊天的時候發現的,它說國內某互聯網公司中有一道筆試題,需要當場寫出無鎖隊列的代碼。當時對於這個概念還是一知半解,後來他說陳皓博客上有相關的內容,本着好學的精神就去一窺究竟:無鎖隊列的實現
基本思想是利用編譯器或者語言提供的原子操作,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獎的書