DAY6 线程
作业1:
多线程实现文件拷贝,线程1拷贝一半,线程2拷贝另一半,主线程回收子线程资源。
代码:
#include <myhead.h>
sem_t sem1;
void *copy1()//子线程1函数 拷贝前一半内容
{
int fd1=open("./1.txt",O_RDONLY);
int fd2=open("./2.txt",O_CREAT|O_RDWR|O_APPEND,0664);
if(fd1==-1)
{
perror("open");
}
if(fd2==-1)
{
perror("open");
}
char s[100];
int sum1=0,res1=0;
int len=lseek(fd1,0,SEEK_END);//统计文件字节数
lseek(fd1,0,SEEK_SET);//统计完光标要返回
while(1)
{
res1=read(fd1,s,sizeof(s));
sum1+=res1;//每读一次,把读取长度加起来
if(res1==0||sum1>len/2)
{
int k=res1-(sum1-len/2);//该次读取字节数-超过len/2的字节数
write(fd2,s,k);
break;
}
write(fd2,s,sizeof(s));//把读取到的字节写入2.txt
}
printf("线程1拷贝完成\n");
close(fd1);
close(fd2);
sem_post(&sem1);
pthread_exit(NULL);
}
void *copy2()//子线程2函数 拷贝后一半内容
{
sem_wait(&sem1);
int fd1=open("./1.txt",O_RDONLY);
int fd2=open("./2.txt",O_CREAT|O_RDWR|O_APPEND,0664);
if(fd1==-1)
{
perror("open");
}
if(fd2==-1)
{
perror("open");
}
int fd3;
int res2=0;
int len=lseek(fd1,0,SEEK_END);//统计文件字节数
lseek(fd1,0,SEEK_SET);//统计完光标要返回
dup2(fd1,fd3);//fd3重定向fd1
lseek(fd3,len/2,SEEK_SET);//fd3光标移动中间
char s[100];
while(1)
{
res2=read(fd3,s,sizeof(s));
if(res2==0)
{
break;
}
write(fd2,s,res2);
}
printf("线程2拷贝完成\n");
close(fd1);
close(fd2);
close(fd3);
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
pthread_t tid1,tid2;
sem_init(&sem1,0,0);
if(pthread_create(&tid1,NULL,copy1,NULL))
{
perror("pthread_create");
return -1;
}
if(pthread_create(&tid2,NULL,copy2,NULL))
{
perror("pthread_create");
return -1;
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
printf("回收完成\n");
sem_destroy(&sem1);
return 0;
}
运行测试结果:
作业2:线程同步之条件变量
生产者先让消费者组成一个队列,生产者生产了一台劳斯莱斯,唤醒第一个消费者来消费,然后再生产第二台劳斯莱斯,唤醒第二个消费者来消费,这样可以精确化的控制生产者线程和消费者线程的协同
代码:
#include <myhead.h>
#define MAX 10
pthread_cond_t cond;
pthread_mutex_t mtx;
sem_t sem;
int n=0,count=0;
void *producer()
{
for(int i=0;i<MAX;i++)
{
sem_wait(&sem);//用条件变量卡一下
n++;
printf("生产了一台特斯拉%d\n",n);
pthread_cond_signal(&cond);//唤醒一个等待线程
}
pthread_exit(NULL);
}
void *consumer()
{
pthread_mutex_lock(&mtx);//进入后锁住
pthread_cond_wait(&cond,&mtx);//条件变量每接受一次进入后重新上锁
count++;
printf("消费了一台特斯拉%d\n",count);
usleep(200000);
pthread_mutex_unlock(&mtx);
sem_post(&sem);//条件变量放行
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
pthread_t tid1,tid2[MAX];
pthread_cond_init(&cond,NULL);//条件变量
pthread_mutex_init(&mtx,NULL);//互斥锁
sem_init(&sem,0,1);//条件变量
if(pthread_create(&tid1,NULL,producer,NULL)!=0)
{
perror("pthread_create");
return -1;
}
for(int i=0;i<MAX;i++)
{
if(pthread_create(&tid2[i],NULL,consumer,NULL)!=0)
{
perror("pthread_create");
return -1;
}
}
pthread_join(tid1,NULL);
for(int i=0;i<MAX;i++)
{
pthread_join(tid2[i],NULL);
}
pthread_mutex_destroy(&mtx);
pthread_cond_destroy(&cond);
return 0;
}
运行测试结果:
作业3:
互斥锁,无名信号量,条件变量再练习一遍
1.互斥锁代码如何实现
代码:
#include <myhead.h>
pthread_mutex_t mtx;//定义互斥锁
void *fun(void *n)
{
pthread_mutex_lock(&mtx);//上锁
printf("%d\n",*(int *)n);
pthread_mutex_unlock(&mtx);//解锁
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
pthread_t tid1,tid2;
int num1=1,num2=2;
pthread_mutex_init(&mtx,NULL);//初始化互斥锁
if(pthread_create(&tid1,NULL,fun,&num1))//子线程1
{
perror("pthread_create");
return -1;
}
if(pthread_create(&tid2,NULL,fun,&num2))//子线程2
{
perror("pthread_create");
return -1;
}
pthread_join(tid1,NULL);//阻塞回收线程
pthread_join(tid2,NULL);
pthread_mutex_destroy(&mtx);//毁锁
return 0;
}
运行测试结果:
2.无名信号量
代码:
#include <myhead.h>
#define MAX 5
sem_t sem;//定义无名信号量
int n=0;
void *producer()
{
for(int i=0;i<MAX;i++)
{
n++;
printf("生产了特斯拉%d\n",n);
}
sem_post(&sem);//释放无名变量
pthread_exit(NULL);
}
void *consumer()
{
sem_wait(&sem);//申请无名变量
printf("消费了一台特斯拉%d\n",n);
n--;
sem_post(&sem);
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
pthread_t tid1,tid[MAX];
sem_init(&sem,0,0);//初始化无名信号量
if(pthread_create(&tid1,NULL,producer,&n)!=0)
{
perror("pthread_create");
return -1;
}
for(int i=0;i<MAX;i++)
{
if(pthread_create(&tid[i],NULL,consumer,&n)!=0)
{
perror("pthread_create");
return -1;
}
}
pthread_join(tid1,NULL);
for(int i=0;i<MAX;i++)
{
pthread_join(tid[i],NULL);
}
sem_destroy(&sem);//销毁无名变量
return 0;
}
运行测试结果:
3.条件变量
见作业2