【回眸】技术干货——Linux 内核 (十六) 之 多线程编程 上

前言

多线程编程的内容稍微有点多,分上下两篇博文。

进程和线程 区别

进程——资源分配的最小单位,线程——程序执行的最小单位

进程有独立的地址空间,线程没有单独的地址空间(同一进程内的线程共享进程的地址空间)。

线程API

多线程开发在 Linux 平台上已经有成熟的 pthread 库支持。其涉及的多线程开发的最基本概念主要包含三点:线程,互斥锁,条件。其中,线程操作又分线程的创建,退出,等待 3 种。互斥锁则包括 4 种操作,分别是创建,销毁,加锁和解锁。条件操作有 5 种操作:创建,销毁,触发,广播和等待。

1.创建线程

#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
// 返回:若成功返回0,否则返回错误编号

2.线程退出 

#include <pthread.h>
int pthread_exit(void *rval_ptr);

​3.线程等待

#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
// 返回:若成功返回0,否则返回错误编号

4.线程脱离

#include <pthread.h>
int pthread_detach(pthread_t thread);
// 返回:若成功返回0,否则返回错误编号

5. 线程ID获取及比较

#include <pthread.h>
pthread_t pthread_self(void);
// 返回:调用线程的ID
#include <pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2);
// 返回:若相等则返回非0值,否则返回0

6.创建及销毁互斥锁

#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
// 返回:若成功返回0,否则返回错误编号
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
// 返回:若成功返回0,否则返回错误编号

7.创建及销毁条件变量

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t cond);
// 返回:若成功返回0,否则返回错误编号

 8. 等待

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);
// 返回:若成功返回0,否则返回错误编号

9.触发

#include <pthread.h>
int pthread_cond_signal(pthread_cond_t cond);
int pthread_cond_broadcast(pthread_cond_t cond);
// 返回:若成功返回0,否则返回错误编号

多线程编程 ​

thread1.c(线程创建)

#include <stdio.h>
#include <pthread.h>

void *func1(void *arg){

printf("t1:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));

}

int main(){
int ret;
int param =100;
pthread_t t1;
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
while(1);

return 0;
}

thread2.c(等待和退出,传整数)

#include <stdio.h>
#include <pthread.h>

void *func1(void *arg){
static int ret = 10;
printf("t1:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
pthread_exit((void *)&ret);

}

int main(){
int ret;
int param =100;
int *pret;
pthread_t t1;
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
//while(1);
pthread_join(t1,(void **)&pret);
printf("main:t1 exit. ret = %d\n", *pret);
return 0;
}

thread3.c(等待和退出 传字符串)

#include <stdio.h>
#include <pthread.h>

void *func1(void *arg){
static char *p = "t1 pijiuya1 is runing.\n";
printf("t1:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
pthread_exit((void *)p);//退出

}

int main(){
int ret;
int param =100;
char *pret = NULL;
pthread_t t1;
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
//while(1);
pthread_join(t1,(void **)&pret);//等待
printf("main:t1 exit. ret = %s\n", pret);
return 0;
}

thread4.c(创建2个)

#include <stdio.h>
#include <pthread.h>

void *func1(void *arg){
static int ret = 10;
printf("t1:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
pthread_exit((void *)&ret);

}

int main(){
int ret;
int param =100;
int *pret;
pthread_t t1;
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
//while(1);
pthread_join(t1,(void **)&pret);
printf("main:t1 exit. ret = %d\n", *pret);
return 0;
}

 thread5.c(创建2个且打印顺序发现多线程共享同一段内存【顺序没有重复】)

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

int g_data = 0;
void *func1(void *arg){

printf("t1:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
while(1){
printf("t1:%d\n",g_data++);
sleep(1);
};


}
void *func2(void *arg){
printf("t2:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t2:param is %d\n",*((int *)arg));
while(1){
printf("t2:%d\n",g_data++);
sleep(1);
};

}
int main(){
int ret;
int param =100;
pthread_t t1;
pthread_t t2;
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
ret = pthread_create(&t2,NULL,func2,(void *)¶m);
if(ret == 0){
printf("main:Create t2 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
while(1){
printf("main:%d\n",g_data++);
sleep(1);
};
pthread_join(t1,NULL);//等待
pthread_join(t2,NULL);//等待
return 0;
}

抢占资源是随机的,每次运行的结果不尽相同。

thread6.c(创建3个线程并且加锁,让t1优先运行且不被t2 t3 打断,t1 释放锁后,t3和t2竞争资源)

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t mutex;
pthread_attr_t attr;
void *func1(void *arg){
int i ;
pthread_mutex_lock(&mutex);//保证t1优先
for(i = 0;i<5;i++){
printf("t1:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
}
pthread_mutex_unlock(&mutex);

}
void *func2(void *arg){
pthread_mutex_lock(&mutex);
printf("t2:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t2:param is %d\n",*((int *)arg));
pthread_mutex_unlock(&mutex);
}
void *func3(void *arg){
pthread_mutex_lock(&mutex);
printf("t3:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t3:param is %d\n",*((int *)arg));
pthread_mutex_unlock(&mutex);
}
int main(){
int ret;
int param =100;
pthread_t t1;
pthread_t t2;
pthread_t t3;
pthread_mutex_init(&mutex,NULL);
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
ret = pthread_create(&t2,NULL,func2,(void *)¶m);
if(ret == 0){
printf("main:Create t2 sucess.\n");
}
ret = pthread_create(&t3,NULL,func3,(void *)¶m);
if(ret == 0){
printf("main:Create t3 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());

pthread_join(t1,NULL);//等待
pthread_join(t2,NULL);//等待
pthread_join(t3,NULL);//等待
pthread_attr_destroy(&attr);
return 0;
}

 thread7.c(fun1先运行到10退出锁,func2后运行不退出)

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t mutex;
pthread_attr_t attr;
int g_data = 0;
void *func1(void *arg){
pthread_mutex_lock(&mutex);//保证t1优先
while(1){
printf("t1:%d\n",g_data++);
sleep(1);
if (g_data == 10){
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
}


}
void *func2(void *arg){

printf("t2:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t2:param is %d\n",*((int *)arg));
while(1){
pthread_mutex_lock(&mutex);
printf("t2:%d\n",g_data);
g_data++;
pthread_mutex_unlock(&mutex);
sleep(1); 
}
}
int main(){
int ret;
int param =100;
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&mutex,NULL);
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
ret = pthread_create(&t2,NULL,func2,(void *)¶m);
if(ret == 0){
printf("main:Create t2 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
printf("main:g_data = %d.\n",g_data);
pthread_join(t1,NULL);//等待
pthread_join(t2,NULL);//等待
pthread_attr_destroy(&attr);
return 0;
}

后记碎碎念

Linux内核是一个系列,可以点击专栏查看同系列的其他文章,希望能帮到屏幕前的每一位应届生往届生,该博文最初发表在CSDN上。

这个多线程的内容在Java里代码很少,回顾了linux这里的互斥锁,感受更加不一样,比当时更加理解了互斥锁的问题。

#校招求职有谈薪空间吗##找工作前vs找工作后的心路变化##租房前辈的忠告##职场中你干过哪些“蠢”事##26届秋招投递记录#
应届生必学实用物联网技术 文章被收录于专栏

本专栏助应届生从物联网小白成长为企业争抢的技术人才,聚焦三大核心技术:传感器应用(环境监测)、嵌入式开发(STM32/Arduino)、通信协议(LoRa/NB-IoT/MQTT),配合10+实战项目(如智能温湿度监控系统)积累项目经验。覆盖智能硬件、工业物联网、智能家居领域岗位需求,解析企业招聘技术重点与面试题,帮电子、计算机、自动化等专业学生构建知识体系,提前锁定名企Offer!

全部评论

相关推荐

2025-12-24 15:25
已编辑
门头沟学院 前端工程师
是腾讯的csig腾讯云,前天晚上九点突然打电话约面,激动的通宵学了一晚上,第二天状态很差改了今天(以后再也不通宵学习了)感觉自己浪费了面试官一个半小时单纯手写+场景,无八股无项目无算法,打击真的很大,全是在面试官提醒的情况下完成的,自己技术方面真的还是有待提高,实力匹配不上大厂和已经面试的两个公司完全不一样,很注重编码能力和解决问题的能力,然而我这两个方面都很薄弱,面试官人很好很耐心的等我写完题目,遇到瓶颈也会提醒我,写不出题也会很耐心的跟我讲解好感动,到最后面试结束还安慰我打算把下周最后一场面试面完之后就不面啦,如果能去实习还是很开心,但是最重要的还是好好努力提高技术以下是面经第一题//&nbsp;实现一个解析&nbsp;url&nbsp;参数的函数function&nbsp;parseUrl(urlStr)&nbsp;{//&nbsp;TODO}parseUrl('*********************************************');//&nbsp;返回&nbsp;{a:&nbsp;1,&nbsp;b:&nbsp;2,&nbsp;c:&nbsp;3}追问:在链接里见过什么部分?用&nbsp;hash&nbsp;路由的话放在哪第二题//&nbsp;考虑有一个异步任务要执行,返回&nbsp;Promise,这个任务可能会失败,请实现&nbsp;retry&nbsp;方法,返回新方法,可以在失败后自动重试指定的次数。/***&nbsp;异步任务重试*&nbsp;@param&nbsp;task&nbsp;要执行的异步任务*&nbsp;@param&nbsp;times&nbsp;需要重试的次数,默认为&nbsp;3&nbsp;次*/function&nbsp;retry(task,&nbsp;times&nbsp;=&nbsp;3)&nbsp;{//&nbsp;TODO:&nbsp;请实现}//&nbsp;---------------测试示例&nbsp;----------------//&nbsp;原方法const&nbsp;request&nbsp;=&nbsp;async&nbsp;(data)&nbsp;=&gt;&nbsp;{//&nbsp;模拟失败if&nbsp;(Math.random()&nbsp;&lt;&nbsp;0.7)&nbsp;{throw&nbsp;new&nbsp;Error('request&nbsp;failed');}const&nbsp;res&nbsp;=&nbsp;await&nbsp;fetch(&#39;https://jsonplaceholder.typicode.com/posts&#39;,&nbsp;{method:&nbsp;'POST',body:&nbsp;JSON.stringify(data),});return&nbsp;res.json();}//&nbsp;新的方法const&nbsp;requestWithRetry&nbsp;=&nbsp;retry(request);//&nbsp;使用async&nbsp;function&nbsp;run()&nbsp;{const&nbsp;res&nbsp;=&nbsp;await&nbsp;requestWithRetry({&nbsp;body:&nbsp;'content'&nbsp;});console.log(res);}run();第三题就是给&nbsp;retry&nbsp;函数添加类型注释,用到泛型第四题:在组件库中将&nbsp;Alert&nbsp;用&nbsp;api&nbsp;的形式实现(应该就是&nbsp;message&nbsp;这个组件)怎么渲染到一个浮层里而不是原地渲染出来
不知道怎么取名字_:技术这个东西,太杂了,而且要下功夫的
查看5道真题和解析
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务