通过互斥锁+条件量的方式实现同步与互斥

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h> // for O_CREAT and O_EXCL
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>

#define SHM_SIZE 4

// 定义条件量,互斥锁和共享内存
int shm_id;
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t flag = PTHREAD_COND_INITIALIZER;

// 线程A
void *increment_thread(void *arg)
{
    while (1)
    {
        pthread_mutex_lock(&mut); // 上锁
        int *buff = (int *)shmat(shm_id, NULL, 0);
        *buff = (*buff) + 1;
        int temp = *buff;
        printf("主线程写入共享内存的值为:%d\n", buff[0]);
        shmdt(buff);
        if (temp % 3 == 0)//判断是否满足条件唤醒线程B
        {
            pthread_cond_broadcast(&flag);
        }
        pthread_mutex_unlock(&mut); // 解锁
        sleep(1);
    }
}

// 线程B
void *decrement_thread(void *arg)
{
    while (1)
    {
        pthread_mutex_lock(&mut);       // 上锁
        pthread_cond_wait(&flag, &mut); // 不满足条件挂起
        int *buff = (int *)shmat(shm_id, NULL, 0);
        printf("\n\n满足条件子线程B输出当前i值为:%d\n\n", buff[0]);
        shmdt(buff);
        pthread_mutex_unlock(&mut); // 解锁
    }
}

int main(int argc, char *argv[])
{
    pthread_t inc_thread, dec_thread;

    // 创建共享内存
    shm_id = shmget(ftok(".", 50), SHM_SIZE, IPC_CREAT | IPC_EXCL | 0644);
    // 函数调用失败,原因是共享内存段已经存在
    if (shm_id == -1)
    {
        if (errno == EEXIST) // 此时可以再次调用函数打开共享内容
        {
            shm_id = shmget(ftok(".", 50), SHM_SIZE, 0644);
        }
        else
        {
            fprintf(stderr, "shmget error,error:%d,%s\n", errno, strerror(errno));
            exit(1);
        }
    }

    // 映射共享内存段到进程空间中并赋予初值1
    int *buff = (int *)shmat(shm_id, NULL, 0);
    if (errno == EEXIST) // 此时可以再次调用函数打开共享内容
    {
        shm_id = shmget(ftok(".", 50), SHM_SIZE, 0644);
    }
    else
    {
        fprintf(stderr, "shmget error,error:%d,%s\n", errno, strerror(errno));
        exit(1);
    }
    *buff = 1;
    shmdt(buff);

    // 创建线程
    if (pthread_create(&inc_thread, NULL, increment_thread, NULL) != 0)
    {
        perror("pthread_create");
        sem_unlink("/sem1");
        sem_unlink("/sem2");
        exit(EXIT_FAILURE);
    }

    if (pthread_create(&dec_thread, NULL, decrement_thread, NULL) != 0)
    {
        perror("pthread_create");
        sem_unlink("/sem1");
        sem_unlink("/sem2");
        exit(EXIT_FAILURE);
    }

    // 等待线程完成
    if (pthread_join(inc_thread, NULL) != 0)
    {
        perror("pthread_join");
        sem_unlink("/sem1");
        sem_unlink("/sem2");
        exit(EXIT_FAILURE);
    }

    if (pthread_join(dec_thread, NULL) != 0)
    {
        perror("pthread_join");
        sem_unlink("/sem1");
        sem_unlink("/sem2");
        exit(EXIT_FAILURE);
    }

    // 关闭共享内存
    shmctl(shm_id, IPC_RMID, NULL);

    printf("All threads completed successfully.\n");
    return 0;
}

参考文献https://blog.csdn.net/daaikuaichuan/article/details/82950711

posted @   藍桉未遇釋槐鳥  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示