如果pthread_mutex_unlock解锁的mutex未被锁上 及 其它


SYNOPSIS

#include <pthread.h>

int pthread_mutex_unlock(pthread_mutex_t *mutex);


DESCRIPTION

The pthread_mutex_unlock() function attempts to unlock the specified mutex. If there are threads blocked on the mutex object when pthread_mutex_unlock() is called, resulting in the mutex becoming available, the scheduling policy is used to determine which thread acquires the mutex.

If the mutex type is PTHREAD_MUTEX_NORMAL, error detection is not provided. If a thread attempts to unlock a mutex that is has not locked or a mutex which is unlocked, undefined behavior results.

If the mutex type is PTHREAD_MUTEX_ERRORCHECK, error checking is provided. If a thread attempts to unlock a mutex that it has not locked or a mutex that is unlocked, an error is returned.

If the mutex type is PTHREAD_MUTEX_RECURSIVE, the mutex maintains the concept of a lock count. When a thread successfully acquires a mutex for the first time, the lock count is set to one. Every time a thread relocks this mutex, the lock count is incremented by one. When the lock count reaches zero, the mutex becomes available for other threads to acquire. If a thread attempts to unlock a mutex that it has not locked or a mutex that is unlocked, an error is returned.

If the mutex type is PTHREAD_MUTEX_DEFAULT, attempting to unlock the mutex if it was not locked by the calling thread results in undefined behavior. Attempting to unlock the mutex if it is not locked results in undefined behavior.

静态定义:
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
The PTHREAD_MUTEX_INITIALIZER macro initializes the static mutex mutex, setting its attributes to default values. This macro should only be used for static mutexes, as no error checking is performed.

动态定义:

pthread_mutex_t mutex;
pthread_mutex_init (&mutex, NULL);

动态定义和静态定义之间的联系:

The pthread_mutex_init() function shall initialize the mutex referenced by mutex with attributes specified by attr. If attr is NULL, the default mutex attributes are used; the effect shall be the same as passing the address of a default mutex attributes object. Upon successful initialization, the state of the mutex becomes initialized and unlocked.

In cases where default mutex attributes are appropriate, the macro PTHREAD_MUTEX_INITIALIZER can be used to initialize mutexes that are statically allocated. The effect shall be equivalent to dynamic initialization by a call to pthread_mutex_init() with parameter attr specified as NULL, except that no error checks are performed.


Reference:

http://www.duangw.net/computer/history/pthread/mutex.html

http://www.ibm.com/developerworks/cn/linux/l-pthred/

http://www.ibm.com/developerworks/cn/linux/sdk/rt/part5/

http://www.ibm.com/developerworks/cn/linux/l-osmig1.html

### 回答问题:`pthread_mutex_lock` 后,`pthread_mutex_lock` 与 `pthread_mutex_unlock` 之间涉及的所有变量都会被保护吗? #### ✅ 简短答案: **不会自动全部被保护!只有你“手动用这个 mutex 保护”的变量才会受保护。** > 🔴 `pthread_mutex_lock` 和 `pthread_mutex_unlock` 只是一个**同步机制的入口和出口**,它并不知道你要保护哪些变量 —— 它只是阻止其他线程同时进入同一段代码区域(临界区)。 --- ### 🔍 详细解释 当你写: ```c pthread_mutex_lock(&mtx); // 在这里访问某些变量 shared_data++; pthread_mutex_unlock(&mtx); ``` 你是在告诉系统:“从 `lock` 到 `unlock` 这段代码是临界区,同一时间只能有一个线程执行”。 但这**不等于所有在这段代码中访问的变量都自动安全了**。是否安全取决于: > ❓ 是否 **所有线程在访问这些共享变量时都使用同一个互斥锁?** --- ### ✅ 正确示例:变量被正确保护 ```c #include <pthread.h> #include <stdio.h> int shared_counter = 0; pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; void* increment(void* arg) { for (int i = 0; i < 100000; i++) { pthread_mutex_lock(&mtx); // 加锁 shared_counter++; // 安全:被锁保护 pthread_mutex_unlock(&mtx); // 解锁 } return NULL; } ``` ✅ 所有对 `shared_counter` 的修改都在 `mtx` 保护下进行 → **线程安全** --- ### ❌ 错误示例:变量被真正保护 ```c int unprotected_data = 0; void* bad_thread_func(void* arg) { pthread_mutex_lock(&mtx); shared_counter++; unprotected_data++; // ⚠️ 危险!这个变量没被任何约定保护! pthread_mutex_unlock(&mtx); return NULL; } ``` 虽然 `unprotected_data++` 写在 `lock` 和 `unlock` 之间,但如果: - 其他线程在**没有加锁的情况下修改了 `unprotected_data`** - 或者你自己在别的地方绕过锁修改了它 那么这个变量依然是**数据竞争(data race)** 的目标! --- ### 🧠 关键理解:互斥锁保护的是“访问路径”,不是“变量本身” 你可以这样理解: > “互斥锁”就像一把门锁,你把房间门锁上(临界区),但只有当**所有人都遵守规则、必须通过这扇门并先敲门(加锁)才能进**时,里面的物品(变量)才是安全的。 如果有人可以从窗户爬进去(无锁访问同一变量),那屋里再怎么上锁也没用。 --- ### ✅ 如何确保变量真正被保护? #### ✔️ 原则:**所有对共享变量的读写操作,都必须使用同一个 mutex 加锁** ```c // 正确做法:无论在哪读写 shared_counter,都要加锁 pthread_mutex_lock(&mtx); printf("Counter: %d\n", shared_counter); // 读也要锁! pthread_mutex_unlock(&mtx); ``` > 即使是“只读”,也可能出现脏读问题(比如读到一半另一个线程改了值) --- ### 💡 更进一步:设计良好的封装 最好将共享数据和其对应的 mutex 封装在一起,并提供受控的访问接口: ```c typedef struct { int balance; char name[64]; pthread_mutex_t lock; // 专属锁 } account_t; // 提供安全的操作函数 void withdraw(account_t* acc, int amount) { pthread_mutex_lock(&acc->lock); if (amount <= acc->balance) { acc->balance -= amount; } pthread_mutex_unlock(&acc->lock); } void deposit(account_t* acc, int amount) { pthread_mutex_lock(&acc->lock); acc->balance += amount; pthread_mutex_unlock(&acc->lock); } ``` 这样就能保证:只要通过这些函数操作 `account_t`,数据就是安全的。 --- ### ⚠️ 常见陷阱 | 错误 | 说明 | |------|------| | 多个变量共用一个锁太粗粒度 | 可能影响性能(串行化) | | 不同变量用了不同的锁但操作需要原子性 | 需要小心死锁或逻辑错误 | | 忘记解锁或提前 return 导致死锁 | 推荐使用 RAII 或 goto 统一释放(C 中常见技巧) | | 使用不同的 mutex 保护同一个变量 | 相当于没保护 | --- ### ✅ 总结 | 问题 | 回答 | |------|------| | `pthread_mutex_lock` 和 `unlock` 之间的变量都被保护了吗? | ❌ 不一定,只有“所有线程都用同一把锁访问”的变量才安全 | | 我把变量放在这两个函数调用之间就安全了吗? | ❌ 错!关键是“访问方式”,而不是“代码位置” | | 如何让变量真正受保护? | ✅ 所有线程在读写该变量时都必须使用同一个互斥锁 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值