进程DAY2

1、为什么要使用线程

多进程间切换会导致要进行CPU上文信息保存,频繁的切换,需要频繁的保存,保存需要资源,对内存的开销会变大!
不建议在程序中出现过多的进程!
进程是程序执行以及资源管理的最小单位,不仅要负责资源管理,还要负责进程的切换以及调度。
能不能分担一下, 进程就负责资源管理就可以, 任务切换以及调度就分配出去,引入了线程!

2、什么是线程,与进程的区别

轻量级的进程就是线程!
创建进程, 子进程几乎会拷贝父进程的全部资源
创建线程, 子线程除了栈区空间之外,其他的资源都与进程是共享的!
进程是资源管理的最小单位,线程是程序执行的最小单位
进程中至少有一个线程。
多任务同时执行!

3、如何创建线程

Linux 中提供了与线程相关的第三方库函数, 创建线程、线程退出、线程资源的回收等等!

3-1、创建线程的函数

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void * (*
routine)(void *), void *arg)
参数1:保存线程id的指针变量
参数2:指定线程的属性,NULL表示使用缺省属性
参数3:函数指针,保存函数地址---函数名,这个函数就是指线程应该做的任务的处理函数
参数4:就给线程处理函数设置的参数
返回值: 0 表示创建线程成功了 , 否则 失败
案例: 模拟摄像头画面实时获取一边显示,一边录制、一边进行语音通话
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void * thread_fun1(void *arg)
{
int count = 0;
while(1)
{
count++;
printf("显示第%d帧图像\n", count);
sleep(1);
}
}
void * thread_fun2(void *arg)
{
int count = 0;
while(1)
{
count++;
printf("保存第%d帧图像\n", count);
sleep(1);
}
}
//如何去定义一个函数指针:复制函数首部,加上分号,在函数名的前面加上*,然后用括号括起来!
int main()
{
int count = 0;
pthread_t pid1, pid2;
int res = pthread_create(&pid1, NULL, thread_fun1, NULL);
if(res<0)
{
perror("pthread create error");
return -1;
}
res = pthread_create(&pid2, NULL, thread_fun2, NULL);
if(res<0)
{
perror("pthread create error");
return -1;
}
while(1)//语音交流
{
count++;
printf("语音交流的第%d句话\n",count);
sleep(1);
}
return 0;
}
验证: 线程的执行的先后顺序是随机的,由 CPU 分配时间片。

3-2、线程资源回收--阻塞式的函数

#include <pthread.h>
int pthread_join(pthread_t thread, void **value_ptr);
参数1:等待的线程
参数2:结束的这个线程反馈回来的数据
返回值: 成功就是0, 否则 -1
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void * thread_fun1(void *arg)
{
int count = 0;
while(1)
{
count++;
printf("显示第%d帧图像\n", count);
sleep(1);
}
}
void * thread_fun2(void *arg)
{
int count = 0;
while(1)
{
count++;
printf("保存第%d帧图像\n", count);
sleep(1);
}
}
//如何去定义一个函数指针:复制函数首部,加上分号,在函数名的前面加上*,然后用括号括起来!
int main()
{
int count = 0;
pthread_t pid1, pid2;
int res = pthread_create(&pid1, NULL, thread_fun1, NULL);
if(res<0)
{
perror("pthread create error");
return -1;
}
res = pthread_create(&pid2, NULL, thread_fun2, NULL);
if(res<0)
{
perror("pthread create error");
return -1;
}
//阻塞等待子线程结束
phread_join(pid1, NULL);
phread_join(pid2, NULL);
while(1)//语音交流
{
count++;
printf("语音交流的第%d句话\n",count);
sleep(1);
}
return 0;
}
验证:主线程的业务没有被处理,只有等两个子线程都结束了,才会执行主线程的业务,这样子的话与我们实际想要的多任务同步执行就不符合了!

3-2、资源回收--非阻塞式的函数

#include <pthread.h>
int pthread_detach(pthread_t thread);
线程分离, 子线程与主线程分离,分离的线程在退出的时候把资源顺带的就回收了!
参数1: 需要与主线程分类的线程ID
返回值:成功 0,否则 -1
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void * thread_fun1(void *arg)
{
int count = 0;
while(1)
{
count++;
printf("显示第%d帧图像\n", count);
sleep(1);
}
}
void * thread_fun2(void *arg)
{
int count = 0;
while(1)
{
count++;
printf("保存第%d帧图像\n", count);
sleep(1);
}
}
//如何去定义一个函数指针:复制函数首部,加上分号,在函数名的前面加上*,然后用括号括起来!
int main()
{
int count = 0;
pthread_t pid1, pid2;
int res = pthread_create(&pid1, NULL, thread_fun1, NULL);
if(res<0)
{
perror("pthread create error");
return -1;
}
res = pthread_create(&pid2, NULL, thread_fun2, NULL);
if(res<0)
{
perror("pthread create error");
return -1;
}
pthread_detach(pid1);
pthread_detach(pid2);
while(1)//语音交流
{
count++;
printf("语音交流的第%d句话\n",count);
sleep(1);
}
return 0;
}
验证:没有阻塞,都在正常执行,但是一旦子线程结束,资源也会被回收!
3-3、线程退出--主动退出
3-4、线程退出--被动退出
printf("语音交流的第%d句话\n",count);
sleep(1);
}
return 0;
}
#include <pthread.h>
int pthread_exit(void *value_ptr)
参数1:退出时可以返回的值,给主线程
返回值: 成功0 失败 -1
#include <pthread.h>
int pthread_cancel(pthread_t thead)
参数1:需要退出的线程的ID
返回值: 成功0 失败 -1
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void * thread_fun1(void *arg)
{
int count = 0;
while(1)
{
count++;
printf("显示第%d帧图像\n", count);
sleep(1);
}
}
void * thread_fun2(void *arg)
{
int count = 0;
while(1)
{
count++;
printf("保存第%d帧图像\n", count);
sleep(1);
if(count == 100)//一个视频已经录制好了
{
break;
}
}
pthread_exit(NULL); //线程主动退出
}
//如何去定义一个函数指针:复制函数首部,加上分号,在函数名的前面加上*,然后用括号括起来!
int main()
{
int count = 0;
pthread_t pid1, pid2;
int res = pthread_create(&pid1, NULL, thread_fun1, NULL);
if(res<0)
{
perror("pthread create error");
return -1;
}
res = pthread_create(&pid2, NULL, thread_fun2, NULL);
if(res<0)
{
perror("pthread create error");
return -1;
}
pthread_detach(pid1);
pthread_detach(pid2);
while(1)//语音交流
{
count++;
printf("语音交流的第%d句话\n",count);
sleep(1);
if(count == 200)
{
//让子线程1退出
pthread_cancel(pid1);
}
}
return 0;
}

4、线程之间数据传输

4-1、验证除了栈区的数据之外,全局变量是否是共享

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
int a = 10;
void *thread_fun1(void *arg)
{
a+=30;
printf("子线程1中a的中为%d\n", a);
sleep(1);
}
void *thread_fun2(void *arg)
{
a+=40;
printf("子线程2中a的中为%d\n", a);
sleep(1);
}
int main()
{
pthread_t pid1, pid2;
pthread_create(&pid1, NULL, thread_fun1, NULL);
pthread_create(&pid2, NULL, thread_fun2, NULL);
a+= 20;
printf("主线程中a的值为%d\n", a);
sleep(1);
pthread_detach(pid1);
pthread_join(pid2, NULL);
return 0;
}

4-2、验证堆区的数据是共享的

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
char *str = NULL;
void *thread_fun1(void *arg)
{
strcpy(str, "I am child 1 thread");
printf("子线程1中str=%s\n", str);
sleep(1);
}
void *thread_fun2(void *arg)
{
strcpy(str, "I am child 2 thread");
printf("子线程2中str=%s\n", str);
sleep(1);
}
int main()
{
pthread_t pid1, pid2;
str = (char *)malloc(50); //动态空间分配
if(str == NULL)
{
perror("malloc error");
return -1;
}
memset(str, 0, 50); // 内存初始化
pthread_create(&pid1, NULL, thread_fun1, NULL);
pthread_create(&pid2, NULL, thread_fun2, NULL);
strcpy(str, "I am main thread");
printf("主线程中str=%s\n", str);
sleep(1);
pthread_detach(pid1);
pthread_join(pid2, NULL);
free(str); //堆区空间记得做释放
return 0;
}

4-3、主线程的数据传递给子线程

通过 pthread_create() 的第四个参数可以实现把数据从主线程传递给子线程

4-4、子线程的数据传递给主线程

子线程通过 pthread_exit() 函数的参数把数据传递给主线程,主线程通过 pthread_join 函数的第二个参数就可以接收到对应的数据!
  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值