第一题
题目:
有三个线程,ID号分别为ABC,且每个线程中都在循环打印自己的ID。要求打印的结果为ABC。
代码:
#include <myhead.h>
//互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int flag = 0; //0:打印A 1:打印B 2:打印C
void *func_1(void *arg)
{
while (1)
{
/**************临界区****************/
//上锁
pthread_mutex_lock(&mutex);
if (flag != 0)
{
//1.解开mutex互斥锁,设置条件变量,同时进入休眠等待被唤醒
pthread_cond_wait(&cond, &mutex);
//2.当收到唤醒信号后,会在短时间内尝试上锁
//3.若上锁成功,则从当前位置继续往后执行后续代码
//4.若上锁失败,则重新回到cond上继续休眠,等待下一次的唤醒信号
}
printf("%c\n", 'A');
flag = 1;
//唤醒睡在指定条件变量上的线程
pthread_cond_signal(&cond);
//解锁
pthread_mutex_unlock(&mutex);
/**************临界区****************/
}
pthread_exit(NULL);
}
void *func_2(void *arg)
{
while (1)
{
/**************临界区****************/
//上锁
pthread_mutex_lock(&mutex);
if (flag != 1)
{
//1.解开mutex互斥锁,设置条件变量,同时进入休眠等待被唤醒
pthread_cond_wait(&cond, &mutex);
}
printf("%c\n", 'B');
flag = 2;
//唤醒睡在指定条件变量上的线程
pthread_cond_signal(&cond);
//解锁
pthread_mutex_unlock(&mutex);
/**************临界区****************/
}
pthread_exit(NULL);
}
void *func_3(void *arg)
{
while (1)
{
/**************临界区****************/
//上锁
pthread_mutex_lock(&mutex);
if (flag != 2)
{
//1.解开mutex互斥锁,设置条件变量,同时进入休眠等待被唤醒
pthread_cond_wait(&cond, &mutex);
}
printf("%c\n", 'C');
flag = 0;
//唤醒睡在指定条件变量上的线程
pthread_cond_signal(&cond);
//解锁
pthread_mutex_unlock(&mutex);
/**************临界区****************/
}
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
//创建三个线程
pthread_t tid_1, tid_2,tid_3;
if (pthread_create(&tid_1, NULL, func_1, NULL) != 0)
{
fprintf(stderr, "pthread_create failed __%d__\n", __LINE__);
return -1;
}
if (pthread_create(&tid_2, NULL, func_2, NULL) != 0)
{
fprintf(stderr, "pthread_create failed __%d__\n", __LINE__);
return -1;
}
if (pthread_create(&tid_3, NULL, func_3, NULL) != 0)
{
fprintf(stderr, "pthread_create failed __%d__\n", __LINE__);
return -1;
}
pthread_join(tid_1, NULL);
pthread_join(tid_2, NULL);
pthread_join(tid_3, NULL);
//销毁互斥锁
pthread_mutex_destroy(&mutex);
//销毁条件变量
pthread_cond_destroy(&cond);
return 0;
}
运行结果:
第二题
题目:
实现AB进程对话。
A进程发送一句话后,B进程接收到打印。然后B进程发送一句话,A进程接收后打印
重复上述步骤。直到AB接收或者发送完quit后,结束AB进程
附加题:在上一题的基础上,实现AB进程能够随时收发,
代码:
进程A
#include <myhead.h>
#include <errno.h>
// 线程执行体
// 读线程
void *receve_Data(void *arg)
{
umask(0);
//创建有名管道文件
if (mkfifo("./fifo1", 0777) < 0)
{
//printf("errno = %d\n" , errno);
if (errno != 17) //17代表文件已经存在,是一个合法错误
{
perror("mkfifo");
return NULL;
}
}
printf("mkfifo success\n");
//以只读的方式打开文件,阻塞
int fd = open("./fifo1", O_RDONLY);
if (fd < 0)
{
perror("open");
return NULL;
}
printf("open fifo1 rdonly success fd= %d\n", fd);
char buf[128] = "";
ssize_t res = 0;
while (1)
{
bzero(buf, sizeof(buf));
//从管道中读取数据,读写端均存在,read函数阻塞
res = read(fd, buf, sizeof(buf));
if (res < 0)
{
perror("read");
return NULL;
}
else if (0 == res)
{
printf("对方进程结束\n"); //所有写端均关闭
break;
}
printf("B说:%s\n", buf);
if (strcmp(buf, "quit") == 0)
break;
}
close(fd);
return NULL;
}
// 写线程
void *send_Data(void *arg)
{
umask(0);
//创建有名管道文件
if (mkfifo("./fifo2", 0777) < 0)
{
//printf("errno = %d\n" , errno);
if (errno != 17) //17代表文件已经存在,是一个合法错误
{
perror("mkfifo");
return NULL;
}
}
printf("mkfifo success\n");
//以只写的方式打开文件,阻塞
int fd = open("./fifo2", O_WRONLY);
if (fd < 0)
{
perror("open");
return NULL;
}
printf("open fifo2 wronly success fd= %d\n", fd);
//从终端获取数据
char buf[128] = "";
while (1)
{
bzero(buf, sizeof(buf));
// 从终端获取数据
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf) - 1] = '\0';
//写入到管道中
if (write(fd, buf, sizeof(buf)) < 0)
{
perror("write");
return NULL;
}
printf("发送成功\n");
if (strcmp(buf, "quit") == 0)
break;
}
close(fd);
return NULL;
}
int main(int argc, const char *argv[])
{
printf("this is A:\n");
// 创建两个线程
pthread_t tid_r, tid_w;
if (pthread_create(&tid_w, NULL, send_Data, NULL) != 0)
{
fprintf(stderr, "pthread_create failed __%d__\n", __LINE__);
return -1;
}
if (pthread_create(&tid_r, NULL, receve_Data, NULL) != 0)
{
fprintf(stderr, "pthread_create failed __%d__\n", __LINE__);
return -1;
}
pthread_join(tid_w, NULL);
pthread_join(tid_r, NULL);
return 0;
}
进程B
#include <myhead.h>
#include <errno.h>
// 线程执行体
// 读线程
void *receve_Data(void *arg)
{
umask(0);
//创建有名管道文件
if (mkfifo("./fifo2", 0777) < 0)
{
//printf("errno = %d\n" , errno);
if (errno != 17) //17代表文件已经存在,是一个合法错误
{
perror("mkfifo");
return NULL;
}
}
printf("mkfifo success\n");
//以只读的方式打开文件,阻塞
int fd = open("./fifo2", O_RDONLY);
if (fd < 0)
{
perror("open");
return NULL;
}
printf("open fifo1 rdonly success fd= %d\n", fd);
char buf[128] = "";
ssize_t res = 0;
while (1)
{
bzero(buf, sizeof(buf));
//从管道中读取数据,读写端均存在,read函数阻塞
res = read(fd, buf, sizeof(buf));
if (res < 0)
{
perror("read");
return NULL;
}
else if (0 == res)
{
printf("对方进程结束\n"); //所有写端均关闭
break;
}
printf("A说:%s\n", buf);
if (strcmp(buf, "quit") == 0)
break;
}
close(fd);
return NULL;
}
// 写线程
void *send_Data(void *arg)
{
umask(0);
//创建有名管道文件
if (mkfifo("./fifo1", 0777) < 0)
{
//printf("errno = %d\n" , errno);
if (errno != 17) //17代表文件已经存在,是一个合法错误
{
perror("mkfifo");
return NULL;
}
}
printf("mkfifo success\n");
//以只写的方式打开文件,阻塞
int fd = open("./fifo1", O_WRONLY);
if (fd < 0)
{
perror("open");
return NULL;
}
printf("open fifo2 wronly success fd= %d\n", fd);
//从终端获取数据
char buf[128] = "";
while (1)
{
bzero(buf, sizeof(buf));
// 从终端获取数据
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf) - 1] = '\0';
//写入到管道中
if (write(fd, buf, sizeof(buf)) < 0)
{
perror("write");
return NULL;
}
printf("发送成功\n");
if (strcmp(buf, "quit") == 0)
break;
}
close(fd);
return NULL;
}
int main(int argc, const char *argv[])
{
printf("this is B:\n");
// 创建两个线程
pthread_t tid_r, tid_w;
if (pthread_create(&tid_w, NULL, send_Data, NULL) != 0)
{
fprintf(stderr, "pthread_create failed __%d__\n", __LINE__);
return -1;
}
if (pthread_create(&tid_r, NULL, receve_Data, NULL) != 0)
{
fprintf(stderr, "pthread_create failed __%d__\n", __LINE__);
return -1;
}
pthread_join(tid_w, NULL);
pthread_join(tid_r, NULL);
return 0;
}
运行结果:
linux