//多个线程操作 / 访问同一块区域(代码),这块代码就称为临界区,在访问临界区的时候只允许一个 (或一类) 线程运行
//当多个线程都要使用临界区资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。
//线程互斥可以看成是一种特殊的线程同步。
#include <rtthread.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
rt_sem_t sem1_handle = NULL;
struct rt_semaphore sem2;
rt_thread_t th1 = NULL,th2 = NULL;
int flag = 1; //临界资源
//IPC flags and control command definitions
// rt_sem_create(name, value, flag);
//信号量创建flag
//#define RT_IPC_FLAG_FIFO 0x00 /**< FIFOed IPC. @ref IPC. */
//#define RT_IPC_FLAG_PRIO 0x01 /**< PRIOed IPC. @ref IPC. */
//信号量获取flag
//#define RT_WAITING_FOREVER -1 /**< Block forever until get resource. */
//#define RT_WAITING_NO 0 /**< Non-block. */
void th1_entry(void *parameter)
{
//如果信号量2的值>0, flag++
while(1)
{
rt_sem_take(&sem2, RT_WAITING_FOREVER);
flag++;
if(flag == 100) flag = 0;
rt_kprintf("th1_entry falg = %d\n",flag);
rt_sem_release(sem1_handle); //释放信号量1.让线程2可以运行
rt_thread_mdelay(1000);
}
}
void th2_entry(void *parameter)
{
//信号量1的值大于0时,线程2才可以执行,否则挂起
while(1)
{
rt_sem_take(sem1_handle, RT_WAITING_FOREVER);
flag--;
if(flag <0 ) flag = 100;
rt_kprintf("th2_entry falg = %d\n",flag);
rt_sem_release(&sem2);//释放信号量2.让线程1可以运行
rt_thread_mdelay(1000);
}
}
int main(void)
{
//动态信号量创建
sem1_handle = rt_sem_create("sem1", 1, RT_IPC_FLAG_FIFO);//信号量值为1,线程2可以执行
if(sem1_handle == RT_NULL){
LOG_E("sem1 rt_sem_create failed...\n");
return RT_ERROR;
}
LOG_D("sem1 rt_sem_create successed...\n");
//静态创建信号量
rt_err_t ret ;
ret = rt_sem_init(&sem2,"sem2", 0, RT_IPC_FLAG_FIFO);//信号量值为0,线程1不可以执行
if(ret != RT_EOK){
LOG_E("sem2 rt_sem_init failed...\n");
return ret;
}
LOG_D("sem2 rt_sem_init successed...\n");
//创建两个线程用来访问临界区域
th1 = rt_thread_create("th1", th1_entry, NULL, 512, 20, 5);
if(th1 == RT_NULL){
LOG_E("th1 rt_thread_create failed...\n");
return RT_ENOMEM;
}
LOG_D("th1 rt_thread_create successed...\n");
rt_thread_startup(th1);
th2 = rt_thread_create("th2", th2_entry, NULL, 512, 20, 5);
if(th2 == RT_NULL){
LOG_E("th2 rt_thread_create failed...\n");
return RT_ENOMEM;
}
LOG_D("th2 rt_thread_create successed...\n");
rt_thread_startup(th2);
return RT_EOK;
}
程序运行结果
[2022-10-25_16:38:10:973]- RT - Thread Operating System
[2022-10-25_16:38:10:973] / | \ 4.0.3 build Oct 24 2022
[2022-10-25_16:38:10:973] 2006 - 2020 Copyright by rt-thread team
[2022-10-25_16:38:10:973][0m[D/main] sem1 rt_sem_create successed...
[2022-10-25_16:38:10:973][0m
[2022-10-25_16:38:10:973][0m[D/main] sem2 rt_sem_init successed...
[2022-10-25_16:38:10:973][0m
[2022-10-25_16:38:10:973][0m[D/main] th1 rt_thread_create successed...
[2022-10-25_16:38:10:991][0m
[2022-10-25_16:38:10:991][0m[D/main] th2 rt_thread_create successed...
[2022-10-25_16:38:10:991][0m
[2022-10-25_16:38:10:991]msh >th2_entry falg = 0
[2022-10-25_16:38:10:991]th1_entry falg = 1
[2022-10-25_16:38:12:000]th2_entry falg = 0
[2022-10-25_16:38:12:000]th1_entry falg = 1
[2022-10-25_16:38:12:997]th2_entry falg = 0
[2022-10-25_16:38:12:997]th1_entry falg = 1
线程2和线程1会轮流循环得到执行,所以flag的0为0->1,0->1变化