既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
头文件:
#include <pthread.h>
/\*
\*函数名:pthread\_create
\*函数功能:创建一个线程
\*函数参数:
\* pthread\_t \*thread:
\* const pthread\_attr\_t \*attr:创建线程时的参数的指针
\* void \*(\*start\_routine) (void \*):线程处理函数的指针
\* void \*arg:线程处理函数的参数
\*函数返回值:int:成功返回0,失败返回非零
\*/
int pthread\_create(pthread_t \*thread, const pthread_attr_t \*attr, void \*(\*start_routine) (void \*), void \*arg);
注意:Compile and link with -pthread. 编译时加-lpthread
6、如何让线程执行特定任务:
通过线程处理函数来实现
7、线程的释放:
(1)pthread_detach
头文件:
#include <pthread.h>
/\*
\*函数名:pthread\_detach
\*函数功能:销毁一个线程
\*函数的参数:
\* pthread\_t thread:要销毁的线程
\*函数返回值:int:成功反回0,失败错误码
\*/
int pthread\_detach(pthread_t thread);
(2)pthread_join
头文件:
#include <pthread.h>
/\*
\*函数名:pthread\_join
\*函数功能:等待线程的退出
\*函数参数:
\* pthread\_t thread:要等待的线程
\* void \*\*retval:线程的退出状态
\*函数返回值:int:成功反回0,失败错误码
\*/
int pthread\_join(pthread_t thread, void \*\*retval);
(3)pthread_exit
(4)pthread_cancel
8.线程代码演示
#include <stdio.h>
#include <pthread.h>
void \*t1f(void \*arg)
{
while(1)
{
printf("Tom and Jerry!\n");
}
return NULL;
}
void \*t2f(void \*arg)
{
while(1)
{
printf("Tomats\n");
}
return NULL;
}
int main()
{
//create thread two
pthread_t tid1, tid2;
int ret = pthread\_create(&tid1, NULL, t1f ,NULL);
if(ret != 0)
{
puts("create thread 1 error.");
return -1;
}
ret = pthread\_create(&tid2, NULL, t2f ,NULL);
if(ret != 0)
{
puts("create thread 1 error.");
return -1;
}
pthread\_detach(tid1);
pthread\_detach(tid2);
//detach thread
while(1)
{};
return 0;
}
二、同步和互斥问题
1.什么是临界资源
并发编程中,多线程/进程 共享的资源,都叫临界资源
2.什么是临界区
代码中操作临界资源的部分,称为临界区
3.操作临界资源的使用要注意哪些问题
读读不互斥
读写互斥
写写互斥
4.如何安全的操作临界资源
同步
互斥
三、同步
1.什么是同步:
多进程/多线程在访问临界资源时,按照一定的操作顺序来访问。
2.什么时候使用同步
需要按照一定的顺序访问临界资源时使用
3.实现同步的方法
1.信号量
有名信号量:进程使用
无名信号量:线程使用
2.能够共享的变量
(1)进程:
管道
------------有名管道
------------无名管道
共享内存
消息队列
(2) 线程:
全局变量
静态变量
4.如何实现无名信号量
(1)sem_init
/\*需要包含的头文件\*/
#include <semaphore.h>
/\*
\*函数名:sem\_init
\*函数功能:初始化一个无名信号量
\*函数参数:
\* sem\_t \*sem:信号量操作对象的指针
\* int pshare:默认为0为线程使用
\* unsigned int value:信号量的初始值
\*函数返回值:int:成功返回0,失败返回-1
\*/
int sem\_init(sem_t \*sem, int pshare, unsigned int value);
(2)sem_wait
(3)sem_post
(4)sem_destroy
/\*需要包含的头文件\*/
#include <semaphore.h>
/\*
\*函数名:sem\_destroy
\*函数功能:销毁一个无名信号量
\*函数参数:sem\_t \*sem:被销毁的无名信号量的操作对象指针
\*函数返回值:int :成功0,失败-1
\*/
int sem\_destroy(sem_t \*sem);
5.如何使用无名信号量
多线程需要同步访问临界资源时使用
6.同步代码演示
(1)flags
create_thread-------------------------------------------------------------------------------------------------代码如下
#include <stdio.h>
#include <pthread.h>
int c;
int flag;
void \*t1f(void \*arg)
{
while(1)
{
if(flag == 0)
{
if(c < 100)
{
c++;
}
else
{
c = 0;
}
flag = 1;
}
}
return NULL;
}
void \*t2f(void \*arg)
{
while(1)
{
if(flag == 1)
{
printf("c:%d\n",c);
flag = 0;
}
}
return NULL;
}
int main()
{
//create thread two
pthread_t tid1, tid2;
int ret = pthread\_create(&tid1, NULL, t1f ,NULL);
if(ret != 0)
{
puts("create thread 1 error.");
return -1;
}
ret = pthread\_create(&tid2, NULL, t2f ,NULL);
if(ret != 0)
{
puts("create thread 1 error.");
return -1;
}
pthread\_detach(tid1);
pthread\_detach(tid2);
//detach thread
while(1)
{};
return 0;
}
(2)unamed_sem
create_thread-------------------------------------------------------------------------------------------------代码如下
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
int c;
sem_t mysem;
void \*t1f(void \*arg)
{
while(1)
{
int sval = 0;
sem\_getvalue(&mysem, &sval);
if(sval == 2)
{
sem\_wait(&mysem);
if(c < 100)
{
c++;
}
else
{
c = 0;
}
}
}
return NULL;
}
void \*t2f(void \*arg)
{
while(1)
{
int sval = 0;
sem\_getvalue(&mysem, &sval);
if(sval == 1)
{
sem\_wait(&mysem);
printf("c:%d\n",c);
sem\_post(&mysem);
sem\_post(&mysem);
}
}
return NULL;
}
int main()
{
//sem\_init
int ret = sem\_init(&mysem,0,2);
if(ret != 0)
{
puts("sem\_init error.");
return -1;
}
//create thread two
pthread_t tid1, tid2;
ret = pthread\_create(&tid1, NULL, t1f ,NULL);
if(ret != 0)
{
puts("create thread 1 error.");
return -1;
}
ret = pthread\_create(&tid2, NULL, t2f ,NULL);
if(ret != 0)
{
puts("create thread 1 error.");
return -1;
}
pthread\_detach(tid1);
pthread\_detach(tid2);
//detach thread
//sem\_destroy
sem\_destroy(&mysem);
while(1)
{};
return 0;
}
四、互斥
1.什么是互斥
多线程/多进程访问临界资源时,没有顺序要求,只需要满足写写互斥和读写互斥时,此时说的就是不能同时访问临界资源。
2.什么时候使用互斥
写写互斥,读写互斥
3.如何实现互斥锁
<1>初始化互斥锁
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
四、互斥
1.什么是互斥
多线程/多进程访问临界资源时,没有顺序要求,只需要满足写写互斥和读写互斥时,此时说的就是不能同时访问临界资源。
2.什么时候使用互斥
写写互斥,读写互斥
3.如何实现互斥锁
<1>初始化互斥锁
[外链图片转存中…(img-6uYpFwSL-1715716648504)]
[外链图片转存中…(img-TK635uNL-1715716648505)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新