金融投资网站模板,在阿里巴巴上做网站需要什么,已满18点此自动转,做网站留后门是怎么回事文章目录 一、线程(LWP)概念二、线程相关函数#xff08;一#xff09;创建 pthread_create1. 定义2. 使用#xff08;不传参#xff09;3. 使用#xff08;单个参数#xff09;4. 使用#xff08;多个参数#xff09;5. 多线程执行的顺序6. 多线程内存空间 #xff0… 文章目录 一、线程(LWP)概念二、线程相关函数一创建 pthread_create1. 定义2. 使用不传参3. 使用单个参数4. 使用多个参数5. 多线程执行的顺序6. 多线程内存空间 二获取线程号 pthread_self三退出线程 pthread_exit四线程 pthread_join五标记分离态 pthread_detach六取消线程pthread_cancel七多线程文件拷贝 三、线程的互斥一定义和初始化二上锁三解锁四销毁 一、线程(LWP)概念
轻量级的进程进程是资源分配的基本单位线程是系统调度的基本单位。
线程不会分配内存空间一个进程中的多个线程是共用进程的内存空间的(0-3G) 多线程没有多进程安全但是多线程的效率更高。
每个线程都有自己的task_struct结构体每个线程都独立的参与时间片轮转
多线程的函数是第三方库实现的。 编码时需要加头文件 #include pthread.h 编译时 需要链接 线程库 -lpthread
线程之间是相互平等的
二、线程相关函数
一创建 pthread_create
1. 定义
#include pthread.hint pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);功能创建线程参数thread线程id tid attr线程属性 NULL 表示默认属性start_routine线程体(线程处理函数)arg给线程处理函数传参的 如果没有参数可传 可以置NULL返回值成功 0失败 错误码注pthread_t是一个long类型的数start_routine是返回值和参数都是void*的函数指针主线程结束整个进程结束
2. 使用不传参
#include my_head.h//线程处理函数
void *task_func(void *arg){printf(我是子线程\n);
}int main(int argc, const char *argv[])
{pthread_t tid 0;int ret 0;if(0 ! (ret pthread_create(tid, NULL, task_func, NULL))){printf(pthread_create : %s\n, strerror(ret));exit(-1);}printf(我是主线程\n);return 0;
}注在不传参时最后一个参数可以置NULL
3. 使用单个参数
4. 使用多个参数
5. 多线程执行的顺序
多线程执行也没有先后顺序也是时间片轮转上下文切换
6. 多线程内存空间
同一个进程中的多个线程共用进程内存空间 全局区、堆区、字符串常量区都是公用的 只有栈区是每个线程独立的作用域问题 线程之间通信简单使用全局变量即可但是不安全
二获取线程号 pthread_self
#include pthread.hpthread_t pthread_self(void);功能获取调用线程的线程号 tid参数无返回值总是会成功 返回tidps -eLf 此时显示的线程号经过了优化方便人查看并非实际的线程号
三退出线程 pthread_exit
#include pthread.h
void pthread_exit(void *retval);
功能退出当前的线程
参数retval退出线程时返回的状态值(其他线程用pthread_join来接收)
返回值无线程退出的四种情况
线程处理函数执行结束线程中调用pthread_exit退出同一进程中的任一线程中调用exit或者主函数return接收到发送的pthread_cancel取消信号时
四线程 pthread_join
结合态线程结束时必须由其他线程并没有要求必须创建这个线程的线程来调用调用pthread_join来回收资源如果结合态的线程结束后没有回收资源默认属性是结合态。 分离态线程结束时由操作系统自动回收其资源
#include pthread.hint pthread_join(pthread_t thread, void **retval);功能等待指定的结合态的线程结束 为其回收资源参数thread等待结束的线程号retval线程结束时的退出状态值 如果不关心可以传NULL返回值成功 0失败 错误码注该函数是阻塞等待第二个参数一般传NULL不关心返回值注意不能返回局部变量的地址可以返回全局变量的地址或者static修饰的局部变量的地址或者malloc在堆区分配的地址但是要注意回收资源的线程要free
五标记分离态 pthread_detach
#include pthread.hint pthread_detach(pthread_t thread);功能标记一个线程为分离态 结束时由操作系统自动回收资源参数thread线程号返回值成功 0失败 错误码注在主线程和子线程本身中标记子线程为分离态均可以但是在子线程中标记自己更好因为线程执行不分先后顺序在子线程中标记可以确保在子线程未执行结束前可以标记成功。一般在子线程开头进行标记当作是线程属性的一种
六取消线程pthread_cancel
#include pthread.h
int pthread_cancel(pthread_t thread);
功能给线程发一个取消的请求目标线程是否以及何时响应这个请求取决于线程的两种属性statu和type
参数thread线程id
返回值成功 0失败 错误码#include pthread.h
int pthread_setcancelstate(int state, int *oldstate);
//设置线程是否可被取消
PTHREAD_CANCEL_ENABLE 可被取消 ----默认属性
PTHREAD_CANCEL_DISABLE 不可被取消#include pthread.h
int pthread_setcanceltype(int type, int *oldtype);
//设置线程的取消类型
PTHREAD_CANCEL_DEFERRED 延时取消 ----默认属性直到线程下一次调用能作为取消点的函数时才会被取消
PTHREAD_CANCEL_ASYNCHRONOUS 立即取消不可被取消不接收取消信号 可被取消立即取消在接收到取消信号后立即取消 可被取消延时取消在接收到取消信号先将当前命令执行完后如果再次遇到可作为取消点的函数时被取消如果遇不到就无法取消
注默认是可被取消延时取消
七多线程文件拷贝
功能需求 使用多线程拷贝文件
代码实现
//实现多线程拷贝文件
#include my_head.htypedef struct _msg{char *src_file;char *dest_file;int offset;int len;
}msg_t;//初始化保证有一个清空的目标文件获取源文件的长度
int init_cp(const char *src_file, const char *dest_file){//打开一个目标文件不存在就创建存在就清空FILE *dest_fpfopen(dest_file,w);if(NULL dest_fp) ERR_LOG(open dest file error);fclose(dest_fp);//获取源文件长度FILE *src_fpfopen(src_file,r);if(NULL src_fp) ERR_LOG(open src file error);fseek(src_fp,0,SEEK_END);int size ftell(src_fp);fclose(src_fp);return size;
}//线程处理函数
void *func_cp(void *argv1){printf(子线程函数:%ld\n,pthread_self());//使用结构体接收参数msg_t t_argv*(msg_t *)argv1;//打开文件int src_fd open(t_argv.src_file,O_RDONLY);if(-1 src_fd) ERR_LOG(open src file error);int dest_fd open(t_argv.dest_file,O_WRONLY);if(-1 dest_fd) ERR_LOG(open dest file error);//将两个文件的指针移动到offset位置lseek(src_fd,t_argv.offset,SEEK_SET);lseek(dest_fd,t_argv.offset,SEEK_SET);//复制函数int w_byte0;//记录写入的字节数int r_byte0;//记录本次读到的字节数char buff[10];//缓冲区while(0 (r_byteread(src_fd,buff,sizeof(buff)))){w_byter_byte;if(w_bytet_argv.len){write(dest_fd,buff,t_argv.len-(w_byte-r_byte));break;}write(dest_fd,buff,r_byte);}//自己就结束了
}int main(int argc, char const *argv[])
{if(3 ! argc){printf(Usage:%s src dest\n,argv[0]);exit(-1);}//初始化int size init_cp(argv[1],argv[2]);char src_path[20]{0};char dest_path[20]{0};strcpy(src_path,argv[1]);strcpy(dest_path,argv[2]);//创建线程msg_t argv2{src_path,dest_path,0,size/2};pthread_t tid10;int sta0;if(sta pthread_create(tid1,NULL,func_cp,(void *)argv2)){printf(pthread_create error:%s\n,strerror(sta));}msg_t argv1{src_path,dest_path,size/2,size-size/2};pthread_t tid20;if(sta pthread_create(tid2,NULL,func_cp,(void *)argv1)){printf(pthread_create error:%s\n,strerror(sta));}pthread_join(tid1,NULL);pthread_join(tid2,NULL);return 0;
}进阶版线程数由命令行传参进来
三、线程的互斥
保证临界资源同一时刻仅被一个线程访问
注上锁范围尽量小尽量在进程访问临界变量时再上锁只有加锁的线程可以解锁对临界变量加锁利用的是锁自身机制一个线程加锁另一个线程想要加锁会阻塞不要出现死锁退出线程前解锁一次只拿一把锁。
一定义和初始化
#include pthread.h
//静态初始化
pthread_mutex_t lock;
pthread_mutex_t lock PTHREAD_MUTEX_INITIALIZER;//静态初始化
//动态初始化互斥锁
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *mutexattr);功能动态初始化互斥锁参数mutex要初始化的锁mutexattr属性 一般传 NULL 默认属性返回值总是会成功 返回0二上锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
功能上锁(如果没有锁可以上锁线程将被阻塞)
参数mutex 互斥锁指针
返回值成功 0 失败 错误码int pthread_mutex_trylock(pthread_mutex_t *mutex);
功能尝试上锁(如果没有锁可以上锁线程不会被阻塞而是立即返回错误)
参数mutex 互斥锁指针
返回值成功 0 失败 错误码三解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);功能解锁(一般使用时只有加锁的线程可以解锁)参数mutex 互斥锁指针返回值成功 0 失败 错误码四销毁
int pthread_mutex_destroy(pthread_mutex_t *mutex);功能在不需要使用互斥锁的时候销毁互斥锁参数mutex 互斥锁指针返回值成功 0 失败 错误码