# 2018q1 第 13 週測驗題
### 測驗 `1`
考慮以下 C 程式:
```Clike=
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#define MAX 5
static int pid;
static pthread_t thread[2];
static pthread_mutex_t mut;
static int number = 0, i;
static void *thread1() {
printf("thread1 : I'm thread 1\n");
for (i = 0; i < MAX; i++) {
printf("thread1 : number = %d\n", number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(2);
}
printf("pid : %d, thread1 : done\n", pid);
pthread_exit(NULL);
}
static void *thread2() {
printf("thread2 : I'm thread 2\n");
for (i = 0; i < MAX; i++) {
printf("thread2 : number = %d\n", number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(3);
}
printf("pid : %d, thread2 : done\n", pid);
pthread_exit(NULL);
}
static void thread_create(void) {
int temp;
memset(&thread, 0, sizeof(thread));
/* Create threads */
if ((temp = pthread_create(&thread[0], NULL, thread1, NULL)))
printf("Thread 1 create fail\n");
else
printf("Thread 1 create successfully\n");
if ((temp = pthread_create(&thread[1], NULL, thread2, NULL)))
printf("Thread 2 create fail");
else
printf("Thread 2 create successfully\n");
}
static void thread_wait(void) {
/* Wait for threads */
if (thread[0]) {
pthread_join(thread[0], NULL);
printf("pid - %d Thread 1 Finished\n", pid);
}
if (thread[1]) {
pthread_join(thread[1], NULL);
printf("pid - %d Thread 2 Finished\n", pid);
}
}
int main() {
pthread_mutex_init(&mut, NULL);
printf("Main thread create threads\n");
thread_create();
pid = fork();
printf("pid-%d Main thread wait for threads\n", pid);
thread_wait();
return 0;
}
```
在 macOS 編譯並執行,得到以下程式輸出:
```
Main thread create threads
Thread 1 create successfully
thread1 : I'm thread 1
thread1 : number = 0
Thread 2 create successfully
thread2 : I'm thread 2
thread2 : number = 0
pid-90400 Main thread wait for threads
pid-0 Main thread wait for threads
pid - 0 Thread 1 Finished
pid - 0 Thread 2 Finished
thread1 : number = 2
thread2 : number = 3
thread1 : number = 4
thread2 : number = 5
pid : 90400, thread1 : done
pid - 90400 Thread 1 Finished
pid : 90400, thread2 : done
pid - 90400 Thread 2 Finished
```
留意第 65 行 `pid = fork();` 敘述,`fork` 系統呼叫觸發後,會「分叉」執行單元為原本的 parent process 和新建立的 child process。從以下選項中挑出最符合的描述。
==作答區==
X = ?
* `(a)` 在 macOS 和 GNU/Linux 有著完全不同的表現,上述輸出不僅 PID 數值不同,連 `number =` 的數值順序也不一樣
* `(b)` 在 child process 中,不具備 `fork` 前由 parent process 建立的 2 個執行緒 (Thread 1 和 2),這點符合 POSIX 規範中 fork 的語意
* `(c)` 受制於 mutex `mut` 的影響,致使 child process 內沒辦法繼續執行 Thread 1 和 2
參考資料: [Mutex lock for Linux Thread Synchronization](https://www.geeksforgeeks.org/mutex-lock-for-linux-thread-synchronization/)
:::info
延伸題目:
1. 解釋程式運作,擴充測試的範圍
2. 參照 [Threads and fork(): think twice before mixing them](http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them),添增 `pthread_atfork()` 來改寫程式碼,使得 child/parent 兩個 process 的執行緒得以交替輸出
:::