Concepts
mutex类似一个flag或者一个lock,用来限制一次只能有一个线程访问某块代码。它会拦住访问代码或者资源的所有其他线程。这确保任何在临界区执行的代码是线程安全的,不会被其他线程破坏。
mutex就像放在咖啡店篮子里的唯一一把钥匙。 该钥匙可用于解锁共用的公共厕所。一个人在他们希望使用共享资源(洗手间)时拿走钥匙,并在完成后归还。 当他们在洗手间时,其他人不得进入。 其他人(类似于线程)必须等待密钥。 当它被归还时,另一个人可能会拿走厕所的钥匙。
如果没有这样的锁机制,很容易出现 race condition,多个线程一起尝试读写一个共享资源。
例如下面例子,两个task都想对全局变量+1,假设加操作不是原子操作,每个task必须从内存中读取全局变量,加1,然后在单独的指令周期中将其写回内存。 因此,我们无法控制其他线程何时可能会中断该进程。
我们可以使用mutex来提供帮助,因为它允许在临界区中互斥线程执行。 在 RTOS 中,互斥锁只是一个可以原子访问的全局(或共享)二进制值。 这意味着如果一个线程拿到互斥锁,它可以读取和递减该值,而不会被其他线程中断。 交还互斥锁(将值加一)也是原子的。
使互斥锁工作的原因,很像队列,是如果互斥锁不可用,线程将被迫等待。 如果一个线程看到一个互斥锁不能被取走,它就会进入阻塞状态,或者它可以在再次检查互斥锁之前做一些其他的工作。
每行表示在处理器上执行的一个(或一组)指令。 请注意,任务 A 只能在具有mutex的情况下递增全局变量。 任务 B 可以中断它,但它不能进入临界区(因为没有可用的互斥锁)。 只有当任务 A 完成并返回互斥锁时,任务 B 才能进入临界区以递增全局变量。
Recommended Reading
introduction-to-rtos-solution-to-part-6-freertos-mutex:https://www.digikey.com/en/maker/projects/introduction-to-rtos-solution-to-part-6-freertos-mutex-example/c6e3581aa2204f1380e83a9b4c3807a6
Difference between “lock” “mutex” and “semaphore”: https://stackoverflow.com/questions/2332765/lock-mutex-semaphore-whats-the-difference
Mutexes and Semaphores Demystified: https://barrgroup.com/embedded-systems/how-to/rtos-mutex-semaphore
FreeRTOS Semaphores (and Mutexes) API reference: https://www.freertos.org/a00113.html