线程同步

线程同步

1.使用信号量实现线程同步

使用的api

1
2
3
int sem_init(sem_t *sem,int shared,int value);	//初始化无名信号灯
int sem_wait(sem_t *sem); //p操作,如果信号量大于0,则信号量-1,函数立即返回,否则函数进入阻塞状态直到信号量大于0
int sem_post(sem_t *sem); //v操作,如果信号量等于0,则信号量+1,函数立即返回,否则函数进入阻塞状态,直到信号量等于0

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <semaphore.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>

#define fifo "/tmp/myfifo"
#define string "myhelloworld"

int fd = 0;
sem_t full, avail, mutex;//初始化三个全局信号量
//生产者线程函数
void *producer(void *arg) {
sem_wait(&avail);
sem_wait(&mutex);
int ret = 0;
int stringlen = strlen(string) + 1;
//action
int i = 0;
while (i < 5) {
ret = write(fd, string, stringlen);
if (ret != stringlen) {
printf("write string to fifo file error!\n");
pthread_exit(NULL);
}
printf("\nwrite string to fifo file successful!\n");
sem_post(&full);
sem_post(&mutex);
sleep(1);
i++;
}
pthread_exit(NULL);
}

//消费者线程函数
void *consumer(void *arg) {
sem_wait(&full);
sem_wait(&mutex);
//action
int ret = 0;
int stringlen = strlen(string) + 1;
char buffer[stringlen];
bzero(buffer, stringlen);
int i = 0;
while (i < 5) {
ret = read(fd, buffer, stringlen);
if (ret != stringlen) {
printf("read string from fifo file error!\n");
pthread_exit(NULL);
}
printf("read string from fifo:%s\n", buffer);
bzero(buffer, stringlen);
i++;
sleep(1);
sem_post(&avail);
sem_post(&mutex);
}

pthread_exit(NULL);
}

int main(int argc, char **argv) {
int ret;
if (F_OK == access(fifo, 0)) {
unlink(fifo);
}
ret = mkfifo(fifo, 0666);
fd = open(fifo, O_RDWR);
if (ret != 0) {
perror("mkfifo");
}
ret = sem_init(&full, 0, 0) + sem_init(&avail, 0, 1) + sem_init(&mutex, 0, 1);
if (ret != 0) {
printf("semphore init failed!\n");
}
pthread_t threadid[2];
//创建两个线程
if (pthread_create(&threadid[0], NULL, producer, NULL) != 0) {
printf("create thread failed!\n");
exit(EXIT_FAILURE);
}
if (pthread_create(&threadid[1], NULL, consumer, NULL) != 0) {
printf("create thread failed!\n");
exit(EXIT_FAILURE);
}

//等待两个线程结束
pthread_join(threadid[0], NULL);
pthread_join(threadid[1], NULL);
}

2.使用线程互斥锁实现线程同步

使用的api

1
2
3
pthread_mutex_t //线程互斥锁类型
pthread_mutex_lock(pthread_mutex_t *mutex); //获取互斥锁
pthread_mutex_unlock(pthread_mutex_t *mutex); //释放互斥锁

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <semaphore.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>
//定义两个宏,一个用于表示fifo文件的路径,一个用于定义一个字符串常量
#define fifo "/tmp/myfifo"
#define string "myhelloworld"

int fd = -1;
pthread_mutex_t mutex;

//生产者线程函数
void *p_operation(void *arg) {
int ret = 0;
static int stringlen = strlen(string) + 1;
//action
int i = 0;
while (i < 5) {
//获得线程锁
pthread_mutex_lock(&mutex);
ret = write(fd, string, stringlen);
if (ret != stringlen) {
printf("write string to fifo file error!\n");
pthread_exit(NULL);
}
printf("write string to fifo file successful!\n");
//释放线程锁
pthread_mutex_unlock(&mutex);
sleep(1);
i++;
}
pthread_exit(NULL);
}

//消费则线程函数
void *v_operation(void *arg) {
//action
int ret = 0;
int stringlen = strlen(string) + 1;
char buffer[stringlen];
bzero(buffer, stringlen);
int i = 0;
while (i < 5) {
pthread_mutex_lock(&mutex);
//获得线程互斥锁
ret = read(fd, buffer, stringlen);
if (ret == stringlen) {
printf("read string from fifo:%s\n", buffer);
bzero(buffer, stringlen);
i++;
}
pthread_mutex_unlock(&mutex);
//释放线程互斥锁
}

pthread_exit(NULL);
}

int main(int argc, char **argv) {
int ret;
if (F_OK == access(fifo, 0)) {
unlink(fifo);
}
ret = mkfifo(fifo, 0666);
fd = open(fifo, O_RDWR);
//将文件描述符设为非阻塞,防止出现死锁(如果没有设置非阻塞,可能会出现一个线程等待数据的到来,而另一个线程在等待线程锁的释放,造成死锁)
int flag = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flag | O_NONBLOCK);
if (ret != 0) {
perror("mkfifo");
}
pthread_mutex_init(&mutex, NULL);
pthread_t threadid[2];
//创建两个线程
if (pthread_create(&threadid[0], NULL, p_operation, NULL) != 0) {
printf("create thread failed!\n");
exit(EXIT_FAILURE);
}
if (pthread_create(&threadid[1], NULL, v_operation, NULL) != 0) {
printf("create thread failed!\n");
exit(EXIT_FAILURE);
}

//等待两个线程结束
pthread_join(threadid[0], NULL);
pthread_join(threadid[1], NULL);
//销毁线程锁
pthread_mutex_destroy(&mutex);
}

线程同步
https://dreamaccount.github.io/2022/04/17/线程同步/
作者
404NotFound
发布于
2022年4月17日
许可协议