当前位置: 首页 > ds >正文

0806线程

Part 1.梳理思维导图

一.线程的意义

由于进程之间的切换,会伴随着cpu的资源转换,需要花费时间。所以创建一个资源共享的线程就成为了解决问题的方法,进程之间的数据交互需要引入同步互斥

二.线程

1.线程时任务执行的最小单位

2.进程包含一个或多个线程

3.多个线程共享一个进程的资源

4.多线程照样遵循时间轮询机制

三.进程和线程的对比

1.线程是任务执行的最小单位,进程是资源分配的最小单位

2.线程之间的数据交互需要引入同步互斥,进程之间的数据交互需要IPC通信机制

3.线程的效率比进程快,进程的资源比线程多

4.线程的安全性要低于进程

四.线程函数

        1.pthread_create

                a.功能:

创建新的线程

                b.原型:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

参数:

pthread_t *thread:创建的新线程的地址

const pthread_attr_t *attr:线程属性

        NULL:结合态

        分离态

void *(*start_routine) (void *):函数的首地址

void *arg:传递参数的指针

                c.使用
#include<myhead.h>void *callback1(void *arg)
{//支线程
}int main(int argc, const char *argv[])
{pthread_t thread1;//创建的支线程名if(0 != pthread_create(&thread1,NULL,callback1,NULL))//支线程名,结合态,支线程函数名,无返回值{printf("thread1 pthread_create error\n");return -1;}//主线程return 0;
}
                d.主线程获得支线程的返回值
#include<myhead.h>void *callback1(void *arg)
{int a = 1;*(int *)arg = &a;printf("支:%d",a);
}int main(int argc, const char *argv[])
{pthread_t thread1;//创建的支线程名int b;if(0 != pthread_create(&thread1,NULL,callback1,&b))//支线程名,结合态,支线程函数名,接收返回值存b{printf("thread1 pthread_create error\n");return -1;}printf("%d",b);return 0;
}
                e.man手册

man pthread_create

        2.pthread_self

                a.功能:

返回调用的线程的线程id

                b.原型

pthread_t pthread_self(void);

                c.使用
#include<myhead.h>void *callback1(void *arg)
{printf("%ld",pthread_self());//输出支线程的线程id
}int main(int argc, const char *argv[])
{pthread_t thread1;//创建的支线程名if(0 != pthread_create(&thread1,NULL,callback1,NULL))//支线程名,结合态,支线程函数名,无返回值{printf("thread1 pthread_create error\n");return -1;}//主线程return 0;
}
                d.man手册

man pthread_self

        3.pthread_exit

                a.功能:

结束线程

                b.原型

void pthread_exit(void *retval);

参数:

void *retval:接收结束的线程的返回值地址

                c.使用
#include<myhead.h>void *callback1(void *arg)
{printf("%ld",pthread_self());pthread_exit(NULL);//不接收返回值
}int main(int argc, const char *argv[])
{pthread_t thread1;if(0 != pthread_create(&thread1,NULL,callback1,NULL)){printf("thread1 pthread_create error\n");return -1;}return 0;
}
                d.man手册

man pthread_exit

        4.pthread_join

                a.功能

阻塞函数,知道支线程结束,并释放完资源

                b.原型

int pthread_join(pthread_t thread, void **retval);

参数:

pthread_t thread:结束的支线程线程id

void **retval:结束的支线程返回值的地址指针

                c.使用
#include<myhead.h>void *callback1(void *arg)
{static int i = 1;printf("%ld",pthread_self());pthread_exit(&i);//不接收返回值
}int main(int argc, const char *argv[])
{pthread_t thread1;if(0 != pthread_create(&thread1,NULL,callback1,NULL)){printf("thread1 pthread_create error\n");return -1;}int *i = NULL;pthread_join(thread1,(void**)&i);return 0;
}
                d.man手册

man pthread_join

        5.pthread_cancel            

                a.功能

给指定线程发送一个取消(退出)请求 但是可以通过取消的类型和状态修改

                b.原型

int pthread_cancel(pthread_t thread);

参数:

pthread_t thread:设置类型

int state

PTHREAD_CANCEL_ENABLE:可以取消

PTHREAD_CANCEL_DISABLE:不可以取消

int type:

PTHREAD_CANCEL_DEFERRED:延时取消

PTHREAD_CANCEL_ASYNCHRONOUS:立刻取消

                c.使用
#include<myhead.h>void *callback(void *arg)
{//pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);//pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);//pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);static int i = 0;while(1){printf("1\n");sleep(1);}printf("支 = %ld\n",pthread_self());pthread_exit(&i);
}int main(int argc, const char *argv[])
{pthread_t thread;if(0 != pthread_create(&thread,NULL,callback,NULL)){printf("pthread_create error\n");return -1;}sleep(3);while(1){//printf("1\n");sleep(1);}pthread_join(thread,NULL);while(1);return 0;
}
                d.man手册

man pthread_cancel

     6.pthread_detach

                a.功能

给指定线程设置分离属性,一旦设置后面就不可以设置结合态(pthread_join是基于结合态的,等于没办法使用该功能

                b.原型

int pthread_detach(pthread_t thread);

                c.使用
#include<myhead.h>void *callback(void *arg)
{static int i = 0;while(1){printf("1\n");sleep(1);}printf("支 = %ld\n",pthread_self());pthread_exit(&i);
}int main(int argc, const char *argv[])
{pthread_t thread;if(0 != pthread_create(&thread,NULL,callback,NULL)){printf("pthread_create error\n");return -1;}sleep(3);pthread_cancel(thread);while(1){//printf("1\n");sleep(1);}pthread_join(thread,NULL);while(1);return 0;
}
                d.man手册

man pthread_detach

Part 2.使用创建两个线程,一个线程拷贝文件的前一部分,另一个线程拷贝文件的后一部分

#include<myhead.h>void *callback1(void *arg)
{FILE *fp = fopen("./protect.c","r");FILE *fp2 = fopen("./cp_protect.c","w");fseek(fp,0,SEEK_END);int len = ftell(fp);rewind(fp);rewind(fp2);char a;for(int i = 0; i < len / 2; i++){if( 1 > fread(&a,1,1,fp))break;fwrite(&a,1,1,fp2);}printf("1\n");fclose(fp);fclose(fp2);pthread_exit(NULL);
}
void *callback2(void *arg)
{	sleep(1);FILE *fp = fopen("./protect.c","r");FILE *fp2 = fopen("./cp_protect.c","a");fseek(fp,0,SEEK_END);int len = ftell(fp);fseek(fp,len/2,SEEK_SET);fseek(fp2,len/2,SEEK_SET);char a;for(int i = len / 2; i < len; i++){if( 1 > fread(&a,1,1,fp))break;fwrite(&a,1,1,fp2);}printf("2\n");fclose(fp);fclose(fp2);pthread_exit(NULL);
}int main(int argc, const char *argv[])
{pthread_t thread1;if(0 != pthread_create(&thread1,NULL,callback1,NULL)){printf("thread1 pthread_create error\n");return -1;}pthread_t thread2;if(0 != pthread_create(&thread2,NULL,callback2,NULL)){printf("thread2 pthread_create error\n");return -1;}pthread_join(thread1,NULL);	pthread_join(thread2,NULL);return 0;
}

Part 3.创建两个线程,一个线程实现字符串的逆置,另一个线程打印字符串,并要求打印顺序是一正一反交替打印 flag

eg:

hello

olleh

hello

olleh

#include<myhead.h>
char a[] = "hello";
void *callback1(void *arg)
{		char *b = (char *)arg;strcpy(b,a);int len = strlen(b);for(int i = 0; i < len/2; i++){char s = b[i];b[i] = b[len-i-1];b[len-i-1] = s;}pthread_exit(NULL);
}
void *callback2(void *arg)
{	sleep(1);int flag = 0;for(int i = 0; i < 10; i++){if(flag){printf("%s\n",(char *)arg);flag = 0;}else if (flag == 0){printf("%s\n",a);flag = 1;}}pthread_exit(NULL);
}int main(int argc, const char *argv[])
{char arr[128] = "";pthread_t thread1;if(0 != pthread_create(&thread1,NULL,callback1,arr)){printf("thread1 pthread_create error\n");return -1;}pthread_t thread2;if(0 != pthread_create(&thread2,NULL,callback2,arr)){printf("thread2 pthread_create error\n");return -1;}pthread_join(thread1,NULL);	pthread_join(thread2,NULL);return 0;
}

http://www.xdnf.cn/news/17295.html

相关文章:

  • MCU程序段的分类
  • http请求结构体解析
  • 【注意】HCIE-Datacom华为数通考试,第四季度将变题!
  • 时隔六年!OpenAI 首发 GPT-OSS 120B / 20B 开源模型:性能、安全与授权细节全解
  • Spring Boot部门管理系统:查询、删除、新增实战
  • 嵌入式处理器指令系统:精简指令集RISC与复杂指令集CISC的简介,及区别
  • 数据结构学习(days04)
  • Node.js- express的基本使用
  • 嵌入式学习---在 Linux 下的 C 语言学习 Day9
  • 《第五篇》基于RapidOCR的图片和PDF文档加载器实现详解
  • 基于单片机GD32E103的HID按键问题分析
  • 日常反思总结
  • electron:vue3+vite打包案例
  • Spring Cloud系列—Eureka服务注册/发现
  • CSS高频属性速查指南
  • 【普通地质学】地球的物质组成
  • Windows 如何上架 iOS 应用?签名上传全流程 + 工具推荐
  • LeetCode——118. 杨辉三角
  • 【Git】修改本地和远程的分支名称
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘chainer’问题
  • 基于AI的自动驾驶汽车(AI-AV)网络安全威胁缓解框架
  • Adobe Analytics 数据分析平台|全渠道客户行为分析与体验优化
  • 【第5话:相机模型1】针孔相机、鱼眼相机模型的介绍及其在自动驾驶中的作用及使用方法
  • 开源流媒体服务器ZLMediaKit 的Java Api实现的Java版ZLMediaKit流媒体服务器-二开视频对话
  • 【java】DDD架构同普通微服务项目的区别
  • DAY 36 复习日
  • MinIO01-入门
  • ara::log::LogStream::WithTag的概念和使用案例
  • Patsy的dmatrix() 函数
  • 利用m0改造循迹模块处理笔记00