各种Mutex的使用与区别

本文详细介绍了多线程程序中不同类型的锁机制,包括普通锁、嵌套锁、纠错锁和自适应锁的特点及使用场景,并通过示例代码演示了这些锁的实际应用。

在多线程的程序中,多线程间一般使用mutex对临界区进行互斥。但这依赖于各线程的协同约定为进入临界区前都必须加锁,而退出临界区前必须解锁,只要其中的一个线程不遵循这个约定就无法做到互斥一致。比如一个函数:

  1. int func()
  2. {
  3.      a++;
  4.      retrun a;
  5. }

要对这个函数进行保护,可以这样做:

  1. lock(mutex);
  2. ret = func();
  3. unlock(mutex);

但更好的做法是直接在函数内部进行保护,如下:

  1. int func()
  2. {
  3.     int b;
  4.     lock(mutex);
  5.     a++;
  6.     b = a;
  7.     unlock(mutex);
  8.     return b; 
  9. }

这样函数提供了自保护,就保证了只要调用这个接口就肯定是协同一致的。

 

一般来说,编程时都约定对一个加上的锁必须由加锁线程本身去解锁。但事实测试发现,对普通锁,一个线程可以去解另一个线程的加上的锁。测试代码如下:

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <pthread.h>
  4. #include <stdlib.h>
  5. pthread_mutex_t tMutex = PTHREAD_MUTEX_INITIALIZER;
  6. void *ThreadFun(void *ptr)
  7. {
  8.     pthread_t tid;
  9.     int i = *((int *)ptr);
  10.     int ret;
  11.     tid = pthread_self();
  12.     pthread_detach(tid);
  13.     if ((i % 2) == 0)
  14.     {   
  15.         printf("[%u] try to lock mutex!/n", tid);
  16.         ret = pthread_mutex_lock(&tMutex);
  17.         if (ret == 0)
  18.         {
  19.             printf("[%u] lock mutex sucess!/n", tid);
  20.         }
  21.         else
  22.         {
  23.             printf("[%u] lock mutex failed!/n", tid);
  24.         }
  25.     }   
  26.     else
  27.     {   
  28.         printf("[%u] try to unlock mutex!/n", tid);
  29.         ret = pthread_mutex_unlock(&tMutex);
  30.         if (ret == 0)
  31.         {
  32.             printf("[%u] unlock mutex sucess!/n", tid);
  33.         }
  34.         else
  35.         {
  36.             printf("[%u] unlock mutex failed!/n", tid);
  37.         }
  38.     }
  39.     sleep(10);
  40.     printf("[%u] exit!/n", tid);
  41. }
  42. int main(int argc, char *argv[])
  43. {
  44.     pthread_t tid;
  45.     int ret;
  46.     int i;
  47.     for (i = 0; i < atoi(argv[1]); i++)
  48.     {
  49.         ret = pthread_create(&tid, NULL, ThreadFun, &i);
  50.         if (ret != 0)
  51.         {
  52.             strerror(ret);
  53.             return 0;
  54.         }
  55.         sleep(1);
  56.     }
  57.     while(1);
  58.     return 0;
  59. }

编译执行结果如下:           
[root@localhost mutexlock]# gcc -D_GNU_SOURCE -o mutex mutex.c -lpthread
[root@localhost mutexlock]# ./mutex 10&
[1] 5165
[root@localhost mutexlock]# [3086166944] try to lock mutex!
[3086166944] lock mutex sucess!
[3075677088] try to unlock mutex!
[3075677088] unlock mutex sucess!
[3065187232] try to lock mutex!
[3065187232] lock mutex sucess!
[3054697376] try to unlock mutex!
[3054697376] unlock mutex sucess!
[3044207520] try to lock mutex!
[3044207520] lock mutex sucess!
[3033717664] try to unlock mutex!
[3033717664] unlock mutex sucess!
[3023227808] try to lock mutex!
[3023227808] lock mutex sucess!
[3012737952] try to unlock mutex!
[3012737952] unlock mutex sucess!
[3002248096] try to lock mutex!
[3002248096] lock mutex sucess!
[2991758240] try to unlock mutex!
[2991758240] unlock mutex sucess!

从上可见,对普通互斥锁,其它线程可以去解另一个线程加上的锁。

如果你想有一种锁强制本线程加上的锁只能由本线程来解的话就可以使用纠错锁,把上面的程序稍微改一下就可以验证纠错锁的特性:

pthread_mutex_t tMutex = PTHREAD_MUTEX_INITIALIZER;
改成
pthread_mutex_t tMutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
编译执行结果如下:
[root@localhost mutexlock]# gcc -D_GNU_SOURCE -o mutex mutex.c -lpthread
[root@localhost mutexlock]# ./mutex 10&
[1] 5226
[root@localhost mutexlock]# [3086744480] try to lock mutex!
[3086744480] lock mutex sucess!
[3076254624] try to unlock mutex!
[3076254624] unlock mutex failed!
[3065764768] try to lock mutex!
[3055274912] try to unlock mutex!
[3055274912] unlock mutex failed!
[3044785056] try to lock mutex!
[3034295200] try to unlock mutex!
[3034295200] unlock mutex failed!
[3023805344] try to lock mutex!
[3013315488] try to unlock mutex!
[3013315488] unlock mutex failed!
[3002825632] try to lock mutex!
[2992335776] try to unlock mutex!
[2992335776] unlock mutex failed!

从上可见,对纠错锁,线程不能去解另一个线程加上的锁。

另外还有递归锁跟自适应锁,这四个锁之间的区别如下:
锁类型  初始化方式                       加解锁特征                              调度特征
普通锁  PTHREAD_MUTEX_INITIALIZER     同一线程可重复加锁,解锁一次释放锁     先等待锁的进程先获得锁
嵌套锁   PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP    同一线程可重复加锁,解锁同样次数才可释放锁    先等待锁的进程先获得锁
纠错锁   PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP   同一线程不能重复加锁,加上的锁只能由本线程解锁  先等待锁的进程先获得锁
自适应锁 PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP     同一线程可重加锁,解锁一次生效      所有等待锁的线程自由竞争 


转自:

http://blog.youkuaiyun.com/guosha/article/details/3136721

相关链接:

http://zhidao.baidu.com/link?url=A5r0uH6LinMokrVjxuH7YGAwU88-fR3MinT9B_Laj-R8U7eczzrAyE7Z0fpQGOBMtrPagvLrEK65IU6_GCr4Ga


<think>好的,我现在需要回答用户关于C#中MutexThread的区别及用法比较的问题。首先,我需要明确这两个概念各自的定义和作用,然后找出它们的区别和联系。 用户给出的引用资料中有几个关键点。引用[3]提到,Mutex用于线程间的同步,而Thread是执行的基本单位。引用[4]说明Mutex通过WaitOne和ReleaseMutex来控制访问,而Thread则是代码执行的流程。我需要将这两者分开,先分别解释它们是什么,再进行比较。 首先,Thread是操作系统能够调度的最小单位,负责执行代码。而Mutex是一种同步机制,用来协调多个线程或进程对共享资源的访问。Mutex属于系统级资源,可以跨进程使用,而Thread仅限于同一进程内。 接下来,引用[2]中的例子展示了Mutex如何防止应用程序被多次启动,这说明Mutex可以跨进程工作。而Thread只能在同一个进程内创建和管理。这应该是一个重要的区别点。 然后,根据引用[3]和[4],Mutex的用法涉及锁定和释放,而Thread的用法更关注如何创建和启动线程,以及管理线程的执行流程。此外,Mutex可能导致线程阻塞,而线程本身是执行的主体,阻塞是同步机制的结果。 还要注意,用户提供的引用中有提到lock和Monitor,这些属于线程同步机制,但用户的问题是关于Mutex和Thread的区别,所以可能需要简要提及这些同步机制,但重点放在Mutex和Thread的比较上。 需要总结它们的核心差异:Mutex是同步工具,用于资源访问控制;Thread是执行单元,用于并发执行代码。同时,Mutex可以跨进程,而Thread不能。此外,Mutex的释放必须显式调用,而Thread的生命周期由操作系统管理。 最后,按照用户要求的结构,先解释两者的定义,再分点比较区别,接着用法比较,最后总结应用场景。同时,生成相关问题,如线程同步的其他方法、跨进程同步的其他方式等。</think>### C#中MutexThread的区别及用法比较 #### 1. 核心定义 - **Thread(线程)** 线程是操作系统调度的最小执行单元,用于实现代码的并发执行。在C#中,通过`System.Threading.Thread`类创建和管理线程,例如: ```csharp Thread t = new Thread(() => Console.WriteLine("子线程执行")); t.Start(); ``` 线程的生命周期包括创建、启动、运行和终止,支持优先级设置和同步机制[^3][^4]。 - **Mutex(互斥锁)** Mutex是一种同步原语,用于控制多线程或跨进程对共享资源的访问。在C#中,通过`System.Threading.Mutex`类实现。其核心方法是`WaitOne()`(获取锁)和`ReleaseMutex()`(释放锁)[^1][^4]。例如: ```csharp Mutex mutex = new Mutex(); mutex.WaitOne(); // 获取锁 // 访问共享资源 mutex.ReleaseMutex(); // 释放锁 ``` #### 2. 核心区别 | **对比维度** | **Mutex** | **Thread** | |--------------------|------------------------------------|---------------------------------| | **作用** | 资源访问同步 | 代码并发执行 | | **作用范围** | 可跨进程(命名Mutex)[^2] | 仅限同一进程内 | | **资源类型** | 系统级内核对象 | 程序内部执行单元 | | **阻塞机制** | 未获取锁的线程会被阻塞 | 线程运行状态由操作系统调度决定 | | **释放方式** | 需显式调用`ReleaseMutex()`[^4] | 线程执行完毕后自动终止 | #### 3. 用法比较 - **Thread的典型场景** - 后台任务处理(如文件下载、日志写入)。 - 并行计算(利用多核CPU提升性能)。 ```csharp Thread worker = new Thread(ProcessData); worker.Start(); ``` - **Mutex的典型场景** - 跨进程同步(如防止程序重复启动)[^2]: ```csharp bool createdNew; Mutex mutex = new Mutex(true, "Global\\MyAppMutex", out createdNew); if (!createdNew) { Console.WriteLine("程序已运行!"); Environment.Exit(0); } ``` - 保护共享资源(如数据库连接池): ```csharp mutex.WaitOne(); // 修改共享数据 mutex.ReleaseMutex(); ``` #### 4. 关键联系 - **依赖关系** Mutex依赖于线程机制实现同步。例如,当一个线程调用`WaitOne()`时,若锁已被占用,该线程会被阻塞,直到其他线程释放锁[^4]。 - **性能影响** Mutex由于涉及内核态切换,性能低于轻量级同步机制(如`lock`关键字)。但在跨进程场景下不可替代[^3]。 #### 5. 总结 - **选择Thread时**:需处理并发任务,如异步I/O、UI响应优化。 - **选择Mutex时**:需跨进程同步或保护关键资源,如单例应用、共享文件访问。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值