#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