互斥锁的错误使用 —— 死锁

死锁指的是一个线程通过加锁占用了一份共享资源,但是这个线程自己又因为某种情况陷入死循环或者永久等待的状态。这里只说明死锁是什么,并不解释如何避免死锁

1、死锁案例

最简单的死锁就是一个线程重复申请锁,我们沿用之前的抢票模型(5个线程同时抢,为了避免线程共享资源冲突,引入了互斥锁)

(12条消息) Linux环境下 解决线程共享资源冲突 —— 互斥锁(代码实现及底层原理)_abs(ln(1+NaN))的博客-优快云博客https://blog.youkuaiyun.com/challenglistic/article/details/124755816?spm=1001.2014.3001.5501我们在申请锁的地方再加一句申请锁的语句,也就是说我们申请了两次互斥锁

 那么最后的结果是进程陷入了永久等待的状态

2、原因分析

为什么会出现这样的情况呢?在互斥锁的底层原理,我们了解到,一个线程一旦申请锁,而且申请成功了,那么这个线程就会一直保存着这个 1 ,一直到解锁才会把 1 还给内存里的mutex;如果申请失败,就会被挂起

回到上面的内容,线程A第一次执行 pthread_mutex_lock(mtx) 就是在向内存的mutex 申请锁,然后mutex很乐意的把锁给了线程A,然后线程A就可以访问临界区了

第二次这个线程A又来找mutex申请锁了,但是此时mutex的值为 0 ,因为锁已经给了线程A,此时会申请失败,此时线程A就会被挂起!

现在线程A被挂起了,被唤醒的条件是 有人把锁还给内存,但是这把锁就在自己手里,但是自己却在等别人把锁还给内存。明明自己骑着驴,却做着找驴的事,这就导致了线程的永久等待。

### FreeRTOS中互斥锁使用方法 在FreeRTOS中,互斥锁是一种重要的同步机制,主要用于保护共享资源,防止多个任务同时访问而导致的数据不一致问题。以下是关于如何正确使用FreeRTOS中的互斥锁的相关说明: #### 创建互斥锁 创建互斥锁可以通过调用`xSemaphoreCreateMutex()`函数实现。该函数会返回一个句柄(handle),用于后续操作此互斥锁。如果成功创建,则返回非NULL值;否则返回NULL。 ```c SemaphoreHandle_t xMutex = xSemaphoreCreateMutex(); if (xMutex == NULL) { // 错误处理逻辑 } ``` 上述代码展示了如何创建一个互斥锁实例[^1]。 #### 获取互斥锁 当某个任务需要访问受保护的共享资源时,应先尝试获取互斥锁。这通常通过`xSemaphoreTake()`函数完成。该函数接受两个参数:第一个互斥锁的句柄,第二个是指定的最大等待时间(以ticks为单位)。如果立即可用,则直接获得锁并继续执行;如果不可用,则阻塞当前任务直到超时或锁被释放。 ```c if (xSemaphoreTake(xMutex, portMAX_DELAY)) { // 成功获取到锁,可以安全地访问共享资源 } else { // 超时未获取到锁的情况下的错误处理 } ``` 这里需要注意的是,在实际应用中应当合理设置等待时间而非总是采用无限期等待(`portMAX_DELAY`)的方式,以免影响系统整体性能和响应速度[^4]。 #### 释放互斥锁 一旦完成了对共享资源的操作之后,应及时释放所持有的互斥锁以便其他可能正在排队等候的任务能够尽快取得使用权。这是通过调用`xSemaphoreGive()`来达成的。 ```c // 完成对sharedVariable的操作后... xSemaphoreGive(xMutex); ``` 以上即构成了基本的互斥锁使用流程——创建、获取、使用及最后释放的过程[^2]。 #### 需要注意的问题 尽管互斥锁能有效解决多线程环境下的资源共享难题,但在具体实践中还需留意诸如优先级反转现象及其解决方案(如支持的优先级继承协议),以及可能出现的各种形式的死锁状况等问题[^3]。 ### 示例代码 下面给出一段完整的示例程序片段展示如何利用FreeRTOS里的互斥锁来进行简单的临界区控制: ```c #include "semphr.h" void vTaskFunction(void *pvParameters){ static int sharedVariable = 0; while(1){ if (xSemaphoreTake(xMutex, pdMS_TO_TICKS(100))) { /* Critical Section Start */ sharedVariable++; /* Critical Section End */ xSemaphoreGive(xMutex); } // 其他非关键部分的工作... } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值