Try   HackMD

2018q1 第 13 週測驗題

測驗 1

考慮以下 C 程式:

#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

延伸題目:

  1. 解釋程式運作,擴充測試的範圍
  2. 參照 Threads and fork(): think twice before mixing them,添增 pthread_atfork() 來改寫程式碼,使得 child/parent 兩個 process 的執行緒得以交替輸出