C++互斥锁和RTOS xMutex之间的区别
Difference between C++ mutex and RTOS xMutex
我正在尝试锁定 ESP32。显然,有不同的方法可以实现锁:
-
有默认的C++互斥库:
#include <mutex> std::mutex mtx; mtx.lock(); mtx.unlock();
-
还有RTOS的实现:
SemaphoreHandle_t xMutex = xSemaphoreCreateMutex(); xSemaphoreTake(xMutex, portMAX_DELAY); xSemaphoreGive(xMutex);
我应该注意哪些根本差异? 还是等价的?
假设您使用的是 ESP-IDF SDK,工具链基于 GCC 5.2,面向 xtensa-lx106 指令集,具有部分开源的 C 运行时库。
在 GNU libstdc++ 中std::mutex
委托pthread_mutex_lock/解锁调用。ESP-IDF SDK 包含一个 pthread 仿真层,我们可以看到pthread_mutex_lock
和pthread_mutex_unlock
实际做了什么:
static int IRAM_ATTR pthread_mutex_lock_internal(esp_pthread_mutex_t *mux, TickType_t tmo)
{
if (!mux) {
return EINVAL;
}
if ((mux->type == PTHREAD_MUTEX_ERRORCHECK) &&
(xSemaphoreGetMutexHolder(mux->sem) == xTaskGetCurrentTaskHandle())) {
return EDEADLK;
}
if (mux->type == PTHREAD_MUTEX_RECURSIVE) {
if (xSemaphoreTakeRecursive(mux->sem, tmo) != pdTRUE) {
return EBUSY;
}
} else {
if (xSemaphoreTake(mux->sem, tmo) != pdTRUE) {
return EBUSY;
}
}
return 0;
}
int IRAM_ATTR pthread_mutex_unlock(pthread_mutex_t *mutex)
{
esp_pthread_mutex_t *mux;
if (!mutex) {
return EINVAL;
}
mux = (esp_pthread_mutex_t *)*mutex;
if (!mux) {
return EINVAL;
}
if (((mux->type == PTHREAD_MUTEX_RECURSIVE) ||
(mux->type == PTHREAD_MUTEX_ERRORCHECK)) &&
(xSemaphoreGetMutexHolder(mux->sem) != xTaskGetCurrentTaskHandle())) {
return EPERM;
}
int ret;
if (mux->type == PTHREAD_MUTEX_RECURSIVE) {
ret = xSemaphoreGiveRecursive(mux->sem);
} else {
ret = xSemaphoreGive(mux->sem);
}
if (ret != pdTRUE) {
assert(false && "Failed to unlock mutex!");
}
return 0;
}
如您所见,它主要将调用委托给 RTOS 信号量 API,并进行一些额外的检查。
您可能不需要/想要这些支票。鉴于 esp32 芯片的微小 i-cache 和极其缓慢的串行 RAM,我宁愿尽可能靠近硬件(即不要使用std::mutex
,除非它完全符合您的需求(。
我应该注意哪些根本差异?
我不熟悉您在第二个示例中调用的 API,但看起来您的xMutex
变量引用了计数信号量。"信号量"抽象比"互斥"抽象更强大。也就是说,您始终可以使用信号量作为互斥锁的替代品,但在某些算法中,互斥锁不能替代信号量。
我喜欢将信号量视为无信息令牌的阻塞队列。 "give"操作将一个令牌放入队列中,而"take"从队列中获取一个令牌,如果队列恰好在调用take((时为空,则可能会等待其他线程提供令牌。
P.S.,为了使用信号量作为互斥锁的替代品,当互斥锁应该"自由"时,你需要它包含一个令牌,当互斥锁应该"正在使用"时,你需要它包含一个令牌,当互斥锁应该"使用中"时,它需要包含零个令牌。 这意味着,您需要创建信号量的代码确保它在开始时包含一个令牌
示例中的xMutex = xSemaphoreCreateMutex()
语句未显式显示新信号灯包含的标记数。 如果是零个标记,那么您可能希望下一行代码"给(("一个标记以完成初始化。
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- int(c) 和 c-'0' 之间的区别。C++
- 在cuda线程之间共享大量常量数据
- 在c代码之间共享数据的最佳方式
- Mix_Init和Mix_OpenAudio SDL之间的区别是什么
- C++ 使用 assign 函数的字符串与直接使用 '=' 更改值的字符串之间的区别
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- std::atomic和std::condition_variable wait,notify_*方法之间的区别
- 大小相等但成员数量不同的结构之间的性能差异
- 类与私有变量的其他类之间的线程安全性
- 如何在cpp文件之间切换窗口?在Qt中
- 线程之间的布尔停止信号
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 在 const 函数中通过引用和指针返回之间的区别
- 我想知道长双倍和双倍之间的区别
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 使用.find函数在c++中查找字符和另一个字符之间的大小
- 构造函数和转换运算符之间的重载解析
- C++互斥锁和RTOS xMutex之间的区别