LoginSignup
1
0

More than 1 year has passed since last update.

C言語 semaphore, mutexを使った並行プログラミングのサンプルコード

Posted at

はじめに

CSAPPを読んで、並行プログラミングの基礎を学んでいます。Mac環境だとサンプルコードを少しいじる必要があったので、メモとしてまとめます。

自分の環境です。

❯ sw_vers    
ProductName:    macOS
ProductVersion: 11.6
BuildVersion:   20G165

スレッドが同期エラーを起こすbadコード

badcnt.c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

volatile long cnt = 0;

void *thread(void *vargp)
{
    long i;
    long niters = *((long *)vargp);

    for (i = 0; i < niters; i++)
    {
        cnt++;
    }
    return NULL;
}

int main(int argc, char **argv)
{
    long niters;
    pthread_t tid1, tid2;

    if (argc != 2) {
        printf("Usage: %s <niters>\n", argv[0]);
        exit(0);
    }
    niters = atoi(argv[1]);
    pthread_create(&tid1, NULL, thread, (void *)&niters);
    pthread_create(&tid2, NULL, thread, (void *)&niters);
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    if (cnt != niters * 2)
        printf("BOOM! cnt = %ld\n", cnt);
    else
        printf("OK cnt=%ld\n", cnt);
    return 0;
}

 実行結果

❯ gcc badcnt.c && ./a.out 1000000       
BOOM! cnt = 1011960

 mutexを使用して相互排他を行ったコード

goodcnt_mutex.c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

volatile long cnt = 0;
pthread_mutex_t lock;

void *thread(void *vargp)
{
    long i;
    long niters = *((long *)vargp);

    for (i = 0; i < niters; i++)
    {
        pthread_mutex_lock(&lock);
        cnt++;
        pthread_mutex_unlock(&lock);
    }
    return NULL;
}

int main(int argc, char **argv)
{
    long niters;
    pthread_t tid1, tid2;

    pthread_mutex_init(&lock, NULL);
    if (argc != 2) {
        printf("Usage: %s <niters>\n", argv[0]);
        exit(0);
    }
    niters = atoi(argv[1]);
    pthread_create(&tid1, NULL, thread, (void *)&niters);
    pthread_create(&tid2, NULL, thread, (void *)&niters);
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    if (cnt != niters * 2)
        printf("BOOM! cnt = %ld\n", cnt);
    else
        printf("OK cnt=%ld\n", cnt);
    return 0;
}

 実行結果

❯ gcc goodcnt_mutex.c && ./a.out 1000000 
OK cnt=2000000

 セマフォを使用して相互排他を行ったコード

goodcnt_sem.c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>

volatile long cnt = 0;
sem_t *mutex;

void *thread(void *vargp)
{
    long i;
    long niters = *((long *)vargp);

    for (i = 0; i < niters; i++)
    {
        sem_wait(mutex);
        cnt++;
        sem_post(mutex);
    }
    return NULL;
}

int main(int argc, char **argv)
{
    long niters;
    pthread_t tid1, tid2;

    mutex = sem_open("/mutex", O_CREAT, 0644, 1);
    if (argc != 2) {
        printf("Usage: %s <niters>\n", argv[0]);
        exit(0);
    }
    niters = atoi(argv[1]);
    pthread_create(&tid1, NULL, thread, (void *)&niters);
    pthread_create(&tid2, NULL, thread, (void *)&niters);
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    if (cnt != niters * 2)
        printf("BOOM! cnt = %ld\n", cnt);
    else
        printf("OK cnt=%ld\n", cnt);
    return 0;
}

 実行結果

❯ gcc goodcnt_sem.c && ./a.out 1000000
OK cnt=2000000

参考文献

CSAPP

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0