在线视频网站如何制作,常用的设计网站有哪些,aspcms上传到虚拟主机后打开网站,建自己的零售网站目录 一、线程与轻量级进程的关系二、进程创建1.线程创建线程创建函数#xff08;pthread#xff09;查看和理解线程id主线程与其他线程之间的关系 三、线程等待#xff08;回收#xff09;四、线程退出线程退出情况线程退出方法 五、线程分离线程的优点线程的缺点 一、线程… 目录 一、线程与轻量级进程的关系二、进程创建1.线程创建线程创建函数pthread查看和理解线程id主线程与其他线程之间的关系 三、线程等待回收四、线程退出线程退出情况线程退出方法 五、线程分离线程的优点线程的缺点 一、线程与轻量级进程的关系
首先我想问一个问题Linux中有没有真线程呢 答案是没有Linux中只有轻量级进程
但是用户不知道“轻量级进程”认为只有进程和线程。因此Linux系统中不会有与线程相关的系统调用只有轻量级进程的系统调用
Linux系统为了能让用户进行正常的使用Linux线程Linux设计者在用户与内核之间设计了一个 pthread库—原生线程库
**作用是将轻量级进程的系统调用进行封装转成线程相关的接口语义提供给用户让用户感觉自己使用的是线程但实际上底层是轻量级进程 **所以我们平时在Linux中使用线程必须带上这个库 不过要注意的是这个库并不属于LInux内核只要是库它就是在用户级实现的因此有许多人将Linux的线程称作“用户级线程”所有线程的实现都是在 用户级实现的
二、进程创建
1.线程创建
线程创建函数pthread
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);thread返回线程IDattr设置线程的属性attr为NULL表示使用默认属性start_routine函数地址线程启动后要执行的函数arg传给线程启动函数的参数返回值成功放回0失败返回错误码
举例
#include iostream
#include pthread.h
#include unistd.h
#include sys/types.hvoid *newthreadrun(void *args)
{while (true){std::cout I am new thread, pid: getpid() std::endl;sleep(1);}
}int main()
{pthread_t tid;pthread_create(tid, nullptr, newthreadrun, nullptr);while (true){std::cout I am main thread, pid: getpid() std::endl;sleep(1);}
}有个注意事项就是如果我们创建线程传递的是 类成员函数 那么就需要将我们的类成员函数声明为static函数因为如果类成员函数的参数中默认会有一个this指针将类成员函数声明为static函数这个成员函数就没有this指针了否则就会造成匹配错误
查看和理解线程id
使用 ps -aL 查看 当我们使用 ps -aL 查看进程时我们会发现除了我们熟知的PID还有一个陌生的LWP
如果这个进程是单进程的话这个PID和LWP是一样的 如果这个进程是多线程的话这个LPW代表不同线程轻量级进程(light weight process)LWP 其中这个PID是主线程的ID
pthread_ create函数会产生一个线程ID存放在第一个参数指向的地址中。该线程ID和前面说的线程ID不是一回事前面讲的线程ID属于进程调度的范畴。因为线程是轻量级进程是操作系统调度器的最小单位所以需要一个数值来唯一表示该线程 pthread_ create函数第一个参数指向一个虚拟内存单元该内存单元的地址即为新创建线程的线程ID属于NPTL线程库的范畴。线程库的后续操作就是根据该线程ID来操作线程的
线程库NPTL提供了pthread_ self函数可以获得线程自身的ID
pthread_t pthread_self(void);主线程与其他线程之间的关系
主线程与其他线程谁先运行 这个答案是不确定的由调度器决定 主线程退出其他线程继续运行还是退出 主线程退出就等同于这个进程退出了而进程是承担分配系统资源的基本实体进程退出了进程所拥有的内部资源也应该被释放也包括内部的执行流等所以只要主线程退出了所有进程都要退出 这也意味着我们的主线程需要最后结束
三、线程等待回收 前面我们学过进程在退出时需要回收它wait否则就会变成僵尸进程而线程同样如此线程也需要被回收wait否则也会造成内存泄漏问题 线程等待函数 pthread_join
int pthread_join(pthread_t thread, void **value_ptr);thread线程idvalue_ptr它指向一个指针后者指向线程的返回值返回值成功返回0失败返回错误码
调用该函数的线程将挂起等待,直到id为thread的线程终止。
thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的: 如果thread线程通过return返回,value_ ptr所指向的单元里存放的是thread线程函数的返回值如果thread线程被别的线程调用pthread_ cancel异常终掉,value_ ptr所指向的单元里存放的是常数 PTHREAD_ CANCELED。如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参数如果对thread线程的终止状态不感兴趣,可以传NULL给value_ ptr参数 四、线程退出
线程退出情况
线程退出无非三种情况
代码跑完结果对代码跑完结构错代码出异常
重点是出异常情况 如果在多线程中任意一个进程出现异常都会导致整个进程退出因此有些人说多线程代码往往健壮性不好 线程退出方法
使用return 从线程函数return。这种方法对主线程不适用,从main函数return相当于调用exit。 使用pthread_exit函数 线程可以调用pthread_ exit终止自己类似于进程退出的exit void pthread_exit(void *value_ptr);无返回值跟进程一样线程结束的时候无法返回到它的调用者自身
需要注意,pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是用malloc分配的,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了
使用pthread_cancel函数 取消一个执行中的线程 int pthread_cancel(pthread_t thread);thread:线程ID返回值成功返回0失败返回错误码
五、线程分离
默认情况下新创建的线程是joinable的也就是说在线程退出后需要对其进行pthread_join操作否则无法释放资源从而造成系统泄漏导致类似僵尸进程的事件
但如果我们的主线程并不关心其他线程的返回值join它是一种负担这个时候我们可以告诉系统当该线程退出时自动释放该线程资源也就是说我们可以将这个线程分离出去可以说使该线程与主线程达到真正的并行
不过所谓的分离只是线程的一种工作状态并不是说页表、进程地址空间等分离了底层依旧属于同一个进程因此当主线程退出时分离线程还是会跟着退出只是不需要等待了
线程并行方法
在主线程分离其他线程
int pthread_detach(pthread_t thread);在该线程中分离线程
pthread_detach(pthread_self());举例
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include pthread.h
void* thread_run(void* arg)
{pthread_detach(pthread_self());printf(%s\n, (char*)arg);return NULL;
}
int main(void)
{pthread_t tid;if (pthread_create(tid, NULL, thread_run, thread1 run...) ! 0) {printf(create thread error\n);return 1;}int ret 0;sleep(1);if (pthread_join(tid, NULL) 0) {printf(pthread wait success\n);ret 0;}else {printf(pthread wait failed\n);ret 1;}return ret;
}线程的优点
创建一个新线程的代价要比创建一个新进程小得多与进程之间的切换相比线程之间的切换需要操作系统做的工作要少很多线程占用的资源要比进程少很多能充分利用多处理器的可并行数量在等待慢速I/O操作结束的同时程序可执行其他的计算任务计算密集型应用为了能在多处理器系统上运行将计算分解到多个线程中实现I/O密集型应用为了提高性能将I/O操作重叠。线程可以同时等待不同的I/O操作。
线程的缺点
性能损失 一个很少被外部事件阻塞的计算密集型线程往往无法与共它线程共享同一个处理器。如果计算密集型 线程的数量比可用的处理器多那么可能会有较大的性能损失这里的性能损失指的是增加了额外的 同步和调度开销而可用的资源不变。 健壮性降低 编写多线程需要更全面更深入的考虑在一个多线程程序里因时间分配上的细微偏差或者因共享了 不该共享的变量而造成不良影响的可能性是很大的换句话说线程之间是缺乏保护的。 缺乏访问控制 进程是访问控制的基本粒度在一个线程中调用某些OS函数会对整个进程造成影响。 编程难度提高 编写与调试一个多线程程序比单线程程序困难得多