线程是计算机科学中的基本概念,指的是在一个进程中执行的独立指令流。通常,一个进程可以包含多个线程,它们共享进程的资源,如内存空间、文件句柄等,但每个线程有自己的独立执行流。线程是操作系统进行调度的最小单元(进程是资源分配的最小单位),它由线程标识符、程序计数器、寄存器集合和堆栈组成。
与进程不同,**线程之间可以更轻松地共享数据和通信,因为它们属于同一个进程,共享相同的地址空间。**这使得线程在并发编程中更为灵活,可以用于实现多任务并行执行。多线程的优点包括提高程序的响应性、资源共享和更高的系统利用率。
然而,多线程编程也带来了一些挑战,如竞态条件(Race Condition)、死锁(Deadlock)等问题,因此在设计和实现多线程程序时需要仔细考虑线程之间的同步和互斥。
进程和线程的区别:
进程有自己独立的地址空间, 多个线程共用同一个地址空间
线程是程序的最小执行单位, 进程是操作系统中最小的资源分配单位
上下文切换:进程/线程分时复用CPU时间片,在切换之前会将上一个任务的状态进行保存, 下次切换回这个任务的时候, 加载这个状态继续运行,任务从保存到再次加载这个过程就是一次上下文切换。
在处理多任务程序的时候使用多线程比使用多进程要更有优势,但是线程并不是越多越好,如何控制线程的个数呢?
pthread_t pthread_self(void); // 返回当前线程的线程ID
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
// Compile and link with -pthread, 线程库的名字叫pthread, 全名: libpthread.so libptread.a
参数:
返回值:线程创建成功返回0,创建失败返回对应的错误号
在编写多线程程序的时候,如果想要让线程退出,但是不会导致虚拟地址空间的释放(针对于主线程),我们就可以调用线程库中的线程退出函数,只要**调用该函数当前线程就马上退出了,并且不会影响到其他线程的正常运行,不管是在子线程或者主线程中都可以使用。**
#include <pthread.h>
void pthread_exit(void *retval);
参数: 线程退出的时候携带的数据,当前子线程的主线程会得到该数据。如果不需要使用,指定为NULL
线程库中提供的线程回收函叫做pthread_join(),这个函数是一个阻塞函数,如果**还有子线程在运行,调用该函数就会阻塞,子线程退出函数解除阻塞进行资源的回收,**函数被调用一次,只能回收一个子线程,如果有多个子线程则需要循环进行回收。
#include <pthread.h>
// 这是一个阻塞函数, 子线程在运行这个函数就阻塞
// 子线程退出, 函数解除阻塞, 回收对应的子线程资源, 类似于回收进程使用的函数 wait()
int pthread_join(pthread_t thread, void **retval);
参数:
返回值:线程回收成功返回0,回收失败返回错误号。
如果让主线程负责子线程的资源回收,调用pthread_join()
只要子线程不退出主线程就会一直被阻塞,主要线程的任务也就不能被执行了。
**在线程库函数中为我们提供了线程分离函数pthread_detach()
,调用这个函数之后指定的子线程就可以和主线程分离,当子线程退出的时候,其占用的内核资源就被系统的其他进程接管并回收了。**线程分离之后在主线程中使用pthread_join()就回收不到子线程资源了。
#include <pthread.h>
// 参数就子线程的线程ID, 主线程就可以和这个子线程分离了
int pthread_detach(pthread_t thread);
代码演示:
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void* callbackFunc(void* arg) {
printf("son thread id: %d\n", pthread_self());
pthread_exit(NULL);
}
int main() {
printf("main thread id: %d\n", pthread_self());
pthread_t mythread;
// 创建新线程 返回0 表示成功
int res = pthread_create(&mythread, NULL, callbackFunc, NULL);
if (res) {
printf("error creating thread:%d\n", res);
return -1;
}
sleep(2);
// 主线程等待新线程结束
// pthread_join(mythread, NULL);
pthread_detach(mythread);
printf("Back in the main thread.\n");
return 0;
}
执行结果: