Linux——线程
Linux——线程
目录
一、线程
1.1 创建一个线程
1.2 主函数等待线程结束pthread_join
为什么输出是乱序的
一、线程
线程:进程内部的一条执行路径
进程:一个正在运行的程序
进程相当于工厂车间,线程就是车间里的许多工人
1.1 创建一个线程
#include <stdio.h> // 包含标准输入输出头文件
#include <string.h> // 包含字符串处理头文件
#include <pthread.h> // 包含POSIX线程库头文件
#include <unistd.h> // 包含POSIX操作系统API头文件,用于sleep函数
// 定义一个线程函数
void* fun(void* arg)
{
for(int i = 0; i < 5; i++)
{
printf("fun run\n");
sleep(1); // 线程休眠1秒
}
}
int main()
{
pthread_t id; // 定义一个线程标识符
// 创建一个线程,执行fun函数
pthread_create(&id, NULL, fun, NULL);
for(int i = 0; i < 5; i++)
{
printf("main run\n");
sleep(1); // 主线程休眠1秒
}
}
pthread_t id;
:定义一个线程标识符id
,用于跟踪创建的线程。
pthread_create(&id, NULL, fun, NULL);
:创建一个新线程,执行fun
函数。第一个参数是线程标识符的地址,第二个参数是线程属性(这里使用NULL
表示使用默认属性),第三个参数是线程函数,第四个参数是传递给线程函数的参数(这里使用NULL
)。在主线程中,使用一个循环打印5次"main run",每次打印后休眠1秒。
pthread_join(id, NULL);
:等待由id
标识的线程结束。这确保主线程在子线程结束后才继续执行。
去掉sleep休眠运行时会发生:
因为线程结束了不会影响主线程,但主线程main结束了,线程fun也会直接结束
1.2 主函数等待线程结束pthread_join
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
void* fun(void* arg)
{
for(int i = 0; i < 5; i++ )
{
printf("fun run\n");
sleep(1);
}
pthread_exit("fun finish");//线程结束并返回一个字符串
}
int main()
{
pthread_t id;
pthread_create(&id,NULL,fun,NULL);//创建线程
for(int i = 0; i < 2; i++ )
{
printf("main run\n");
sleep(1);
}
char* s = NULL;
pthread_join(id,(void**)&s);//阻塞,等待线程结束,并获取返回值
printf("s=%s\n",s );//打印线程返回值
exit(0);
}
pthread_exit:用于终止一个线程的执行,并可以选择性地返回一个值给等待该线程结束的其他线程。这个函数是线程的“退出点”,
pthread_join :
int pthread_join(pthread_t thread, void** retval);
pthread_t thread
:目标线程的ID,标识要等待的线程。这个ID是在调用pthread_create
时返回的。
void** retval
:一个指向指针的指针,用于存储目标线程的返回值。如果目标线程调用了pthread_exit
并返回了一个值,这个值将被存储在*retval
中。如果不需要获取返回值,可以传递NULL
。
pthread_join
通常用于以下场景:主线程等待子线程结束:在多线程程序中,主线程可能需要等待子线程完成任务后再继续执行。
获取线程返回值:如果线程需要返回一个值给主线程或其他线程,可以通过
pthread_join
获取这个值。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
// 线程函数
void* fun(void* arg) {
int *p = (int*)arg; // 将void*类型的参数转换为int*类型
int index = *p; // 获取线程的索引值
printf("index=%d\n", index); // 打印线程索引
pthread_exit(NULL); // 线程结束,返回NULL
}
int main() {
pthread_t ids[5]; // 定义一个数组,用于存储5个线程的ID
int i = 0;
// 创建5个线程
for (; i < 5; i++) {
pthread_create(&ids[i], NULL, fun, &i); // 创建线程,并将i的地址传递给线程函数
}
// 等待5个线程结束
for (i = 0; i < 5; i++) {
pthread_join(ids[i], NULL); // 等待线程结束
}
exit(0); // 正常退出程序
}
创建了5个线程,每个线程都打印了一个索引值。然而,输出的顺序并不是按照线程创建的顺序(0到4),而是出现了一些乱序的情况。这种情况发生的原因主要与线程调度有关。每次运行程序时,由于线程调度的不确定性,输出的顺序可能会有所不同。
线程调度是由操作系统负责的,它决定哪个线程在什么时候运行。在多线程程序中,线程的执行顺序可能会因为操作系统的调度策略而变得不确定。
为什么输出是乱序的
并发执行:当多个线程被创建后,它们可能同时处于就绪状态,等待CPU时间片来执行。操作系统的线程调度器会根据一定的策略(如优先级、时间片轮转等)来决定哪个线程获得CPU时间片,从而得以执行。
时间片轮转:在时间片轮转调度算法中,每个线程会被分配一个时间片,即允许它运行的时间。当一个线程的时间片用完后,如果它还没有完成,它会被放到就绪队列的末尾,等待下一次调度。
线程切换:操作系统会在不同的线程之间快速切换,使得每个线程都能获得执行的机会。这种快速切换可能会在很短的时间内发生,从而给用户一种多个线程同时运行的错觉。