# 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 的執行緒得以交替輸出 :::