目录
1.作业一
使用信号量实现
// 要求定义一个全局变量 char buf[] = "1234567",创建两个线程,不考虑退出条件。
// A线程循环打印buf字符串,
// B线程循环倒置buf字符串,即buf中本来存储1234567,倒置后buf中存储7654321. 不打印!!
// 倒置不允许使用辅助数组。
// 要求A线程打印出来的结果只能为 1234567 或者 7654321 不允许出现7634521 7234567
// 不允许使用sleep函数
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
sem_t sem1, sem2;
char buf[] = "1234567";
/// @brief 线程体A
void* taskA(void* arg);
/// @brief 线程体B
void* taskB(void* arg);
int main(int argc, const char* argv[])
{
// 创建信号量
sem_init(&sem1, 0, 1);
sem_init(&sem2, 0, 0);
// 创建线程
pthread_t tidA, tidB;
if (pthread_create(&tidA, NULL, taskA, NULL) != 0) {
printf("pthread_create tidA error\n");
return -1;
}
if (pthread_create(&tidB, NULL, taskB, NULL) != 0) {
printf("pthread_create tidB error\n");
return -1;
}
// 阻塞等待线程A退出
pthread_join(tidA, NULL);
pthread_join(tidB, NULL);
return 0;
}
void* taskA(void* arg)
{
while (1) {
// 获取信号
sem_wait(&sem1);
// 打印buf
printf("%s\n", buf);
// 释放信号
sem_post(&sem2);
}
}
void* taskB(void* arg)
{
while (1) {
sem_wait(&sem2);
int start = 0; // 第一个字符下标
int end = sizeof(buf) - 2; // 最后一个字符下标
// 逆置
while (start < end) {
buf[start] = buf[start] ^ buf[end];
buf[end] = buf[start] ^ buf[end];
buf[start] = buf[start] ^ buf[end];
start++;
end--;
}
sem_post(&sem1);
}
}
2.作业二
// 1.将一个文件中的数据打印到终端,类似cat一个文件,要求如下:
// 一个线程读取文件中的数据
// 另外一个线程打印文件中的数据
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
// 定义信号量
sem_t sem1, sem2;
char buf[32] = "";
void* task1(void* arg)
{
int len = 0;
while (1) {
// 获取信号量
sem_wait(&sem1);
len = read(*(int*)arg, buf, sizeof(buf));
buf[len] = '\0';
sem_post(&sem2);
if (len == 0) {
break;
}
}
pthread_exit(NULL);
}
void* task2(void* arg)
{
while (1) {
// 获取信号量
sem_wait(&sem2);
if (strlen(buf) == 0) {
break;
}
printf("%s", buf);
memset(buf, 0, sizeof(buf));
sem_post(&sem1);
}
pthread_exit(NULL);
}
int main(int argc, const char* argv[])
{
// 1.校验参数
if (argc != 2) {
printf("input error\n");
printf("usage: ./a.out filename\n");
return -1;
}
// 2.打开文件
int fd = open(argv[1], O_RDONLY);
if (-1 == fd) {
perror("open");
return -1;
}
sem_init(&sem1, 0, 1);
sem_init(&sem2, 0, 0);
// 4.创建线程
pthread_t tid1, tid2;
if (pthread_create(&tid1, NULL, task1, &fd) != 0) {
printf("pthread_create tiad1 error\n");
return -1;
}
if (pthread_create(&tid2, NULL, task2, buf) != 0) {
printf("pthread_create tiad2 error\n");
return -1;
}
// 阻塞等待回收子线程资源
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
close(fd);
return 0;
}
3.作业三
// 2.现有ID号为a b c的三个线程,每个线程的任务都是循环打印自己id号,要求打印的顺序为abc
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
// 定义互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// 定义条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int flags = 0;
char* buf = "ABC";
int i = 0;
void* task(void* arg)
{
while (1) {
// 获取锁,上锁,阻塞其他线程
pthread_mutex_lock(&mutex);
// 判断标识
while (flags == 0) {
pthread_cond_wait(&cond, &mutex); // 入队之后,代码会阻塞在这里
}
flags = 0; // 将flags置0,防止其他线程被唤醒
printf("%c--->%ld\n", buf[i], pthread_self());
if (++i > 2) {
i = 0;
}
// 解锁
pthread_mutex_unlock(&mutex);
}
}
int main(int argc, const char* argv[])
{
pthread_t tidA, tidB, tidC;
if (pthread_create(&tidA, NULL, task, NULL) != 0) {
printf("pthread_create tiadA error\n");
return -1;
}
if (pthread_create(&tidB, NULL, task, NULL) != 0) {
printf("pthread_create tiadB error\n");
return -1;
}
if (pthread_create(&tidC, NULL, task, NULL) != 0) {
printf("pthread_create tiadC error\n");
return -1;
}
while (1) {
sleep(1);
flags = 1;
pthread_cond_signal(&cond);
}
return 0;
}
4.思维导图