mutex和unmaed semaphore,线程同步

Last Updated: 2023-07-02 14:11:12 Sunday

-- TOC --

线程间常用的同步方式,互斥量和信号量。值为1的信号量与互斥量效果一样。

互斥量

pthread_mutex_t可以定义一个mutex互斥量。

匿名信号量

unamed semaphore is also called memory-based semaphore!

semaphore信号量与mutex不同之处在于,semaphore可以有一个大于0的值,P操作-1,V操作+1,只是不能让这个值小于0。当值为0的时候,P操作阻塞,等待另一个线程的V操作释放一个资源出来。

当semaphore的值为1时,它的行为与mutex很相似。

下面是测试代码:

$ cat test_sem_thread.c
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/wait.h>
#include <pthread.h>


#define _PEXIT \
    do {\
        char ebuf[64] = {0};\
        sprintf(ebuf, "%s: %d", __FILE__, __LINE__);\
        perror(ebuf);\
        exit(errno);\
    }while(0)


sem_t sem;
char *file_name = "number.txt";


void increment1(void) {
    sem_wait(&sem);

    int a;
    FILE *fp = fopen(file_name, "r");
    fscanf(fp, "%d", &a);
    fclose(fp);

    fp = fopen(file_name, "w");
    fprintf(fp, "%d", a+1);
    fclose(fp);

    sem_post(&sem);
}


int main(int argc, char **argv) {
    /* thread number */
    int tnum;
    if (argc == 2)
        tnum = atoi(argv[1]);
    else
        tnum = 4;  /* default thread number */

    /* create a file which contain a number zero */
    FILE *fp = fopen(file_name, "w");
    if (fp == NULL)
        _PEXIT;
    fprintf(fp, "%d", 0);
    fclose(fp);

    /* init a semaphore between threads with value 1 */
    if (sem_init(&sem, 0, 1) != 0)
        _PEXIT;

    /* create threads */
    pthread_t *tid = (pthread_t*)malloc(sizeof(pthread_t)*tnum);
    if (tid == NULL) {
        fprintf(stderr, "malloc failed\n");
        return 1;
    }    
    pthread_t tmp_tid;
    int i;
    for (i=0; i<tnum; ++i) {
        if (pthread_create(&tmp_tid, NULL, (void*)increment1, NULL) != 0)
            _PEXIT;
        tid[i] = tmp_tid;
    }

    /* wait all */
    for (i=0; i<tnum; ++i)
        pthread_join(tid[i], NULL);

    /* free mem */
    free(tid);

    /* read out final number */
    int a;
    fp = fopen(file_name, "r");
    fscanf(fp, "%d", &a);
    fclose(fp);
    printf("%d\n", a);

    /* close semaphore */
    sem_destroy(&sem);
    /* delete file */
    unlink(file_name);

    return 0;
}

运行效果如下:

$ gcc -Wall -Wextra test_sem_thread.c -o test_sem_thread -lpthread
$ ./test_sem_thread
4
$ ./test_sem_thread 234
234
$ ./test_sem_thread 234567
test_sem_thread.c: 70: Resource temporarily unavailable  # too many threads
$ ./test_sem_thread 2345
2345

匿名信号量也可用于进程间的同步,sem_init接口的第2个参数置1,但需要进程间存在共享内存,要将此信号量放在共享内存中。具体参考:man 3 sem_init

本文链接:https://cs.pynote.net/sf/linux/prog/202208013/

-- EOF --

-- MORE --