所謂緩衝,本質上是同一塊資料在不同空間的儲存。這樣的例子很多:
※ CPU和記憶體之間的快取;
※ 同時映射到兩個進程地址空間的資料,典型的是共用記憶體;
※ 同時位於資料庫和記憶體中的同一個業務資料,如O-R映射;
※ 位於兩台伺服器的資料,典型的例子是叢集全域配置資訊。
一、訪問緩衝可能發生的簡單問題:
1、在同一個儲存空間中,不同進程/線程間的共用資料一致性問題。
例如,假設有一個表示姓名的資料結構被兩個線程A、B共用:
struct name {
char* first;
char* last;
}
假設線程A要修改姓名,步驟如下:
第一步,修改name.first
第二步,修改name.last
如果線程B在第一步和第二步之間讀取name,那麼它將獲得的是不匹配的“姓”和“名”。
2、在不同儲存空間中,資料的一致性問題。
仍然以上面的資料為例,這次假設同樣的資料在記憶體和資料庫中各有一份。如果線程A要修改姓名,步驟如下:
第一步:修改記憶體中的name資料;
第二步:將資料儲存在資料庫中(修改資料庫中的name資料)。
同樣,如果在第一步和第二步之間,B先從資料庫中讀取了name,再與記憶體中的name比較,就會探索資料不一致問題。
雖然上述兩個問題看起來都是由於不同儲存空間(記憶體的不同地區、記憶體和資料庫)造成的資料一致性。其實,這兩個問題本質是不同的,問題1是兩份有關聯的資料間的一致性問題;問題2是同一份資料在不同儲存空間中的一致性問題。
二、解決思路
1、Copy-on-Write方法
對於被多個線程共用的資料來說,如果一個線程要修改資料,步驟如下:
第一步:將要求改的資料D複製一份,作為線程私人資料D’;
第二步:對D’進行所需的修改;
第三步:查看D從第一步到現在是否未被被其他線程修改過。如果是,則用D’替換D;否則重新從第一步開始。
第三步其實是一個CAS過程(Compare and Set),要求是一個原子操作。上述過程常用迴圈來類比:
while (true) {
D’ = copy(D);
modify(D’);
if CAS( !modified(D) , D’)
break;
}
2、加鎖方法
對於被多個線程共用的資料來說,如果一個線程要修改資料,步驟如下:
第一步:對要修改的資料D加獨佔鎖定(X鎖),阻止其他線程訪問;
第二步:修改資料D;
第三步:解除資料D上的鎖。
方法1正是所謂無鎖結構(lock-free),相比方法2並發要效能高一些,但是複雜性也相對高一些。而且,方法1通常也可用鎖機制來類比,只是加鎖時間短暫一些,通常被稱為spin-lock(旋轉鎖)。
上述兩個方法的根本,有其共同之處,就是要保證:在共用資料被修改完成以前,不能被其他線程訪問。
三、稍微複雜一些的緩衝管理問題
1、階層的資料一致性問題。
例如下面的資料結構中,結構name是結構person的成員:
struct name {
char* first;
char* last;
}
stuct person {
int id;
struct name full_name;
}
如果我們要通過加鎖的方式更新person的資料,就要考慮是否對person.full_name也加鎖。
2、寫緩衝的時機
對於需要在兩種儲存介質中儲存的某種資訊,必須考慮何時同步這兩種儲存中的資料。例如,記憶體和資料庫中的資料同步;記憶體和磁碟之間的資料同步;CPU和記憶體之間的資料同步。
3、緩衝的透明性
這就首先要考慮下面兩個問題。
1)沖機制的引入,與沒有緩衝相比,是否需要對外暴露更多的介面。
考慮為保證一致性而引入鎖機制,對編程介面的影響。最直觀的方案,就是要求程式員必須顯式的進行“加鎖/解鎖”操作:
lock(d);
*d = new_value;
unlock(d);
另一種方案,就是對外不暴露鎖機制,由架構內部完成:
change(data* d, data new_value) {
lock(d);
*d = new_value;
unlock(d);
}
雖然後一種方案看起來先進一些,但其實對於比較複雜的資料結構來說,要求實現被修改資料實現深拷貝(deep copy)介面。
2)是不是每次修改資料,都要同步資料。
對於一個較複雜的資料結構來說,我們可能常常一次只修改其中的一部分資料。例如:
name.first = “Tom”;
/* 進行其他動作 */
/* … */
name.last = “Smith”;
有時,如果修改每一部分資料都進行同步操作,分散寫入資料,不但步驟比較繁瑣,而且效率不如集中寫入高。如果讓緩衝管理機制來決定何時寫入資料,可能即方便又高效。但是,這樣做也有新的問題,一方面實現起來比較複雜,另一方面,如果系統崩潰,可能造成緩衝中為寫入的資料丟失。
這就引出了其他機制,回寫、直寫、先寫日誌和檢查點等各種新的概念和技術。