1.将一个文件中的数据打印到终端上,类似cat一个文件,要求如下:
1.1A线程读取文件中的数据
1.2B线程将A线程读取到的数据打印到终端上
1.3文件打印完毕后,结束进程
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
sem_t sem1,sem2;
char str[32] = "";
ssize_t res_r;
void* pthread_read(void* arg)
{
//一个线程读取文件中数据
//打开文件
int fd = open((char*)arg,O_RDONLY);
if(-1 == fd){
perror("open");
pthread_exit(NULL);
}
if(-1 == lseek(fd,0,SEEK_SET)){
printf("lseek fail\n");
pthread_exit(NULL);
}
while(1){
if(sem_wait(&sem1) < 0){
perror("sem_wait");
break;
} //p操作
//读取文件
//str[32] = "";
memset(str,0,sizeof(str));
res_r = read(fd,str,sizeof(str));
if(-1 == res_r){
printf("read fail\n");
break;
}else if(sizeof(str) != res_r){
//printf("文件读取完毕\n");
sem_post(&sem2);
break;
}
if(sem_post(&sem2) < 0){
perror("sem_post1");
break;
} //v操作
}
pthread_exit(NULL);
}
void* pthread_printf()
{
//一个线程将读取到的数据打印出来
while(1){
if(sem_wait(&sem2) < 0){
perror("sem_wait");
break;
}
printf("%s",str);
if(res_r != sizeof(str)){
printf("\n");
break;
}
if(sem_post(&sem1) < 0){
perror("sem_post1");
break;
}
}
pthread_exit(NULL);
}
int main(int argc, char const *argv[])
{
if(argc<2){
printf("请输入要读取的文件名\n");
return -1;
}
//申请信号量
//使用PV操作实现
if(sem_init(&sem1,0,1) < 0){
perror("sem_init");
return -1;
}
if(sem_init(&sem2,0,0) < 0){
perror("sem_init");
return -1;
}
//创建两个线程
pthread_t thread_r,thread_p;
if(pthread_create(&thread_r,NULL,pthread_read,(void*)argv[1]) != 0){ //命令行输入要打开的文件
printf("pthread_create:thread_r faill!\n");
return -1;
}
if(pthread_create(&thread_p,NULL,pthread_printf,NULL) != 0){
printf("pthread_create:thread_p faill!\n");
return -1;
}
//销毁信号量
if(-1 == sem_destroy(&sem1)){
perror("sem_destory");
return -1;
}
if(-1 == sem_destroy(&sem2)){
perror("sem_destory");
return -1;
}
//回收两个线程
if(0 != pthread_join(thread_r,NULL)){
printf("pthread_join1 fail\n");
}
if(0 != pthread_join(thread_p,NULL)){
printf("pthread_join2 fail\n");
}
return 0;
}
效果展示如图1
图1
2.用条件变量实现,有编号为ABC的三个线程,线程内分别打印自己的线程编号,要求打印的顺序为ABC
#include<stdio.h>
#include<pthread.h>
pthread_cond_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond3 = PTHREAD_COND_INITIALIZER;
int flag = 0;
void* pthread_a(void* arg)
{
while(1){
/***********临界区***********/
//上锁
pthread_mutex_lock(&mutex);
//如果不是当前线程要访问的时机,则需要让当前线程休眠
if(flag != 0){
//1.解开互斥锁,阻塞当前进程,让当前进程进入休眠阶段,等待被唤醒
pthread_cond_wait(&cond1,&mutex);
}
printf("A\t");
flag = 1;
//唤醒:唤醒睡在指定条件变量上的线程
pthread_cond_signal(&cond2);
//解锁
pthread_mutex_unlock(&mutex);
/**************临界区***********/
}
pthread_exit(NULL);
}
void* pthread_b(void* arg)
{
while(1){
/***********临界区***********/
//上锁
pthread_mutex_lock(&mutex);
//如果不是当前线程要访问的时机,则需要让当前线程休眠
if(flag != 1){
//1.解开互斥锁,阻塞当前进程,让当前进程进入休眠阶段,等待被唤醒
pthread_cond_wait(&cond2,&mutex);
}
printf("B\t");
flag = 2;
//唤醒:唤醒睡在指定条件变量上的线程
pthread_cond_signal(&cond3);
//解锁
pthread_mutex_unlock(&mutex);
/**************临界区***********/
}
pthread_exit(NULL);
}
void* pthread_c(void* arg)
{
while(1){
/***********临界区***********/
//上锁
pthread_mutex_lock(&mutex);
//如果不是当前线程要访问的时机,则需要让当前线程休眠
if(flag != 2){
//1.解开互斥锁,阻塞当前进程,让当前进程进入休眠阶段,等待被唤醒
pthread_cond_wait(&cond3,&mutex);
}
printf("C\n");
flag = 0;
//唤醒:唤醒睡在指定条件变量上的线程
pthread_cond_signal(&cond1);
//解锁
pthread_mutex_unlock(&mutex);
/**************临界区***********/
}
pthread_exit(NULL);
}
int main(int argc, char const *argv[])
{
//创建线程
pthread_t thread_a,thread_b,thread_c;
if(pthread_create(&thread_a,NULL,pthread_a,NULL) != 0){
printf("pthread_create:thread_a faill!\n");
return -1;
}
if(pthread_create(&thread_b,NULL,pthread_b,NULL) != 0){
printf("pthread_create:thread_b faill!\n");
return -1;
}
if(pthread_create(&thread_c,NULL,pthread_c,NULL) != 0){
printf("pthread_create:thread_c faill!\n");
return -1;
}
//回收线程
pthread_join(thread_a,NULL);
pthread_join(thread_b,NULL);
pthread_join(thread_c,NULL);
//销毁互斥锁
pthread_mutex_destroy(&mutex);
//销毁条件变量
pthread_cond_destroy(&cond1);
pthread_cond_destroy(&cond2);
pthread_cond_destroy(&cond3);
return 0;
}
效果展示如图2
图2