/*
  gcc -g mutex.cpp -o mutex -lpthread

  minGW64で、Mutexを使ってみる
  
  このプログラムだと、

  pass1-1
  pass1-2
  pass1-3
  pass2-1
  pass2-2
  pass2-3

  のように出力される。

  pthread_mutex_lock(&mutex);
  と
  pthread_mutex_unlock(&mutex);

  で囲まれた部分が一括で処理されるのが分かる

  上記をコメントアウトすると出力の様子が変ってくるのが確認できる。


*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // usleep()

// スレッド関数1
void* threadFunc1(void* param);
// スレッド関数2
void* threadFunc2(void* param);


// スレッド間で変数を保護するmutex
pthread_mutex_t mutex;

/**
 * メイン関数
 */
int main(int argc, char* argv[]) {
 
    // スレッド1識別変数の宣言
    pthread_t thread1;
    // スレッド2識別変数の宣言
    pthread_t thread2;
 
 
    // mutex初期化
    pthread_mutex_init(&mutex, NULL);
 
    // スレッド1の生成
    pthread_create(&thread1, NULL, threadFunc1, NULL);
 
    // スレッド2の生成
    pthread_create(&thread2, NULL, threadFunc2, NULL);
 
    // スレッド1の終了待ち
    pthread_join(thread1, NULL);
 
    // スレッド2の終了待ち
    pthread_join(thread2, NULL);
     
    // mutex破棄
    pthread_mutex_destroy(&mutex);
 
    printf("mutex destroyed...\n");
 
    return EXIT_SUCCESS;
}
 
 
/**
 * スレッド関数1実装:
 */
void* threadFunc1(void* param) {
  
  while (1) {
    
    // mutexロック
    pthread_mutex_lock(&mutex);
    
    printf("pass1-1\n");fflush(stdout);
    
    usleep(5000);
    
    printf("pass1-2\n");fflush(stdout);
    
    usleep(5000);
    
    printf("pass1-3\n");fflush(stdout);
    
    // mutexアンロック
    pthread_mutex_unlock(&mutex);
    
    usleep(10000);
  }
  
}
 
/*
 * スレッド関数2実装:
 */
void* threadFunc2(void* param) {
  
  while (1) {
    
    // mutexロック
    pthread_mutex_lock(&mutex);
    
    printf("pass2-1\n");fflush(stdout);
    
    usleep(5000);
    
    printf("pass2-2\n");fflush(stdout);
    
    usleep(5000);
    
    printf("pass2-3\n");fflush(stdout);
    
    // mutexアンロック
    pthread_mutex_unlock(&mutex);
    
    usleep(5000);
  }
}