# 同步復習題
> 原文:<https://github.com/angrave/SystemProgramming/wiki/Synchronization-Review-Questions>
## 話題
* 原子操作
* 關鍵部分
* 生產者消費者問題
* 使用條件變量
* 使用計數信號量
* 實施障礙
* 實現環形緩沖區
* 使用 pthread_mutex
* 實施生產者消費者
* 分析多線程編碼
## 問題
* 什么是原子操作?
* 為什么以下不能在并行代碼中工作
```c
//In the global section
size_t a;
//In pthread function
for(int i = 0; i < 100000000; i++) a++;
```
這會嗎?
```c
//In the global section
atomic_size_t a;
//In pthread function
for(int i = 0; i < 100000000; i++) atomic_fetch_add(a, 1);
```
* 原子操作有哪些缺點?什么會更快:保持局部變量或許多原子操作?
* 什么是關鍵部分?
* 一旦確定了一個關鍵部分,確保一次只有一個線程在該部分中的一種方法是什么?
* 在此確定關鍵部分
```c
struct linked_list;
struct node;
void add_linked_list(linked_list *ll, void* elem){
node* packaged = new_node(elem);
if(ll->head){
ll->head =
}else{
packaged->next = ll->head;
ll->head = packaged;
ll->size++;
}
}
void* pop_elem(linked_list *ll, size_t index){
if(index >= ll->size) return NULL;
node *i, *prev;
for(i = ll->head; i && index; i = i->next, index--){
prev = i;
}
//i points to the element we need to pop, prev before
if(prev->next) prev->next = prev->next->next;
ll->size--;
void* elem = i->elem;
destroy_node(i);
return elem;
}
```
你有多緊張關鍵部分?
* 什么是生產者消費者問題?在上一節中如何使用上述生產者消費者問題?生產者消費者問題與讀者作家問題有什么關系?
* 什么是條件變量?為什么在`while`循環上使用一個有優勢?
* 為什么這段代碼很危險?
```c
if(not_ready){
pthread_cond_wait(&cv, &mtx);
}
```
* 什么是計數信號量?給我一個餅干罐/披薩盒/限量食品的類比。
* 什么是線程障礙?
* 使用計數信號量來實現屏障。
* 編寫生產者/消費者隊列,生產者消費者棧怎么樣?
* 給我一個帶條件變量的讀寫器鎖的實現,用你需要的任何東西制作一個結構,它只需要能夠支持以下函數
```c
void reader_lock(rw_lock_t* lck);
void writer_lock(rw_lock_t* lck);
void reader_unlock(rw_lock_t* lck);
void writer_unlock(rw_lock_t* lck);
```
唯一的規范是在`reader_lock`和`reader_unlock`之間,沒有編寫者可以寫。在寫入器鎖之間,一次只能寫一個作者。
* 編寫代碼以使用僅三個計數信號量來實現生產者使用者。假設可以有多個線程調用 enqueue 和 dequeue。確定每個信號量的初始值。
* 編寫代碼以使用條件變量和互斥鎖實現生產者使用者。假設可以有多個線程調用 enqueue 和 dequeue。
* 使用 CV 實現 add(unsigned int)和 subtract(unsigned int)阻塞函數,這些函數永遠不會允許全局值大于 100。
* 使用 CV 為 15 個線程實現屏障。
* 以下有多少陳述是正確的?
* 可以有多個活躍的讀者
* 可以有多個活動作者
* 當有活動的寫入器時,活動讀取器的數量必須為零
* 如果有活動的閱讀器,則活動寫入器的數量必須為零
* 作者必須等到當前活躍的讀者完成
* Todo:分析多線程代碼片段
- UIUC CS241 系統編程中文講義
- 0. 簡介
- #Informal 詞匯表
- #Piazza:何時以及如何尋求幫助
- 編程技巧,第 1 部分
- 系統編程短篇小說和歌曲
- 1.學習 C
- C 編程,第 1 部分:簡介
- C 編程,第 2 部分:文本輸入和輸出
- C 編程,第 3 部分:常見問題
- C 編程,第 4 部分:字符串和結構
- C 編程,第 5 部分:調試
- C 編程,復習題
- 2.進程
- 進程,第 1 部分:簡介
- 分叉,第 1 部分:簡介
- 分叉,第 2 部分:Fork,Exec,等等
- 進程控制,第 1 部分:使用信號等待宏
- 進程復習題
- 3.內存和分配器
- 內存,第 1 部分:堆內存簡介
- 內存,第 2 部分:實現內存分配器
- 內存,第 3 部分:粉碎堆棧示例
- 內存復習題
- 4.介紹 Pthreads
- Pthreads,第 1 部分:簡介
- Pthreads,第 2 部分:實踐中的用法
- Pthreads,第 3 部分:并行問題(獎金)
- Pthread 復習題
- 5.同步
- 同步,第 1 部分:互斥鎖
- 同步,第 2 部分:計算信號量
- 同步,第 3 部分:使用互斥鎖和信號量
- 同步,第 4 部分:臨界區問題
- 同步,第 5 部分:條件變量
- 同步,第 6 部分:實現障礙
- 同步,第 7 部分:讀者編寫器問題
- 同步,第 8 部分:環形緩沖區示例
- 同步復習題
- 6.死鎖
- 死鎖,第 1 部分:資源分配圖
- 死鎖,第 2 部分:死鎖條件
- 死鎖,第 3 部分:餐飲哲學家
- 死鎖復習題
- 7.進程間通信&amp;調度
- 虛擬內存,第 1 部分:虛擬內存簡介
- 管道,第 1 部分:管道介紹
- 管道,第 2 部分:管道編程秘密
- 文件,第 1 部分:使用文件
- 調度,第 1 部分:調度過程
- 調度,第 2 部分:調度過程:算法
- IPC 復習題
- 8.網絡
- POSIX,第 1 部分:錯誤處理
- 網絡,第 1 部分:簡介
- 網絡,第 2 部分:使用 getaddrinfo
- 網絡,第 3 部分:構建一個簡單的 TCP 客戶端
- 網絡,第 4 部分:構建一個簡單的 TCP 服務器
- 網絡,第 5 部分:關閉端口,重用端口和其他技巧
- 網絡,第 6 部分:創建 UDP 服務器
- 網絡,第 7 部分:非阻塞 I O,select()和 epoll
- RPC,第 1 部分:遠程過程調用簡介
- 網絡復習題
- 9.文件系統
- 文件系統,第 1 部分:簡介
- 文件系統,第 2 部分:文件是 inode(其他一切只是數據...)
- 文件系統,第 3 部分:權限
- 文件系統,第 4 部分:使用目錄
- 文件系統,第 5 部分:虛擬文件系統
- 文件系統,第 6 部分:內存映射文件和共享內存
- 文件系統,第 7 部分:可擴展且可靠的文件系統
- 文件系統,第 8 部分:從 Android 設備中刪除預裝的惡意軟件
- 文件系統,第 9 部分:磁盤塊示例
- 文件系統復習題
- 10.信號
- 過程控制,第 1 部分:使用信號等待宏
- 信號,第 2 部分:待處理的信號和信號掩碼
- 信號,第 3 部分:提高信號
- 信號,第 4 部分:信號
- 信號復習題
- 考試練習題
- 考試主題
- C 編程:復習題
- 多線程編程:復習題
- 同步概念:復習題
- 記憶:復習題
- 管道:復習題
- 文件系統:復習題
- 網絡:復習題
- 信號:復習題
- 系統編程笑話