什么是互斥锁?

互斥锁是一个经常用于解决多线程问题的编程概念。我对社区的问题:

什么是互斥锁以及如何使用它?

417652 次浏览

当你有一个多线程的应用程序时,不同的线程有时会共享一个公共资源,例如变量或类似的资源。这个共享的源通常不能同时访问,因此需要一个构造来确保一次只有一个线程在使用该资源。

这个概念被称为“互斥”(短Mutex),是一种确保该区域内只允许一个线程使用该资源等的方法。

如何使用它们是特定于语言的,但通常(如果不总是)基于操作系统互斥锁。

由于范式的原因,有些语言不需要这种结构,例如函数式编程(Haskell、ML是很好的例子)。

MutualEx排除。这是维基百科上的条目。

互斥锁的目的是同步两个线程。当有两个线程尝试访问单个资源时,一般模式是让第一个代码块尝试访问以在进入代码之前设置互斥锁。当第二个代码块尝试访问时,它会看到互斥锁已设置,并等待直到第一个代码块完成(并取消互斥锁),然后继续。

如何实现这一点的具体细节显然因编程语言而异。

Mutex是一个Mut实际上的独立标志。它充当一段代码的门卫,允许一个线程进入并阻止对所有其他线程的访问。这确保被控制的代码一次只被一个线程击中。完成后一定要释放互斥锁。:)

我在工作中热烈讨论问题的时候,就用我办公桌里的橡皮鸡,这种场合我就用橡皮鸡。拿着鸡的人是唯一可以说话的人。如果你不拿着鸡,你就不能说话。你只能表示你想要鸡,等到你拿到鸡后再说话。你说完后,你可以把鸡还给主持人,主持人会把鸡交给下一个人说话。这样既保证了人们不会互相说话,也有自己的说话空间。

用互斥锁和带线程的人替换鸡,你基本上有了互斥锁的概念。

当然,没有橡胶互斥锁这种东西。只有橡胶鸡。我的猫曾经有一只橡胶老鼠,但它们吃了它。

当然,在你使用橡皮鸡之前,你需要问问自己,你是否真的需要5个人在一个房间里,一个人在房间里做所有的工作不是更容易吗?实际上,这只是扩大类比,但你明白了。

在C#中,常用的互斥锁是监控。类型是'系统。线程。监视器'。它也可以通过'锁(对象)'语句隐式使用。它的一个使用示例是在构造Singleton类时。

private static readonly Object instanceLock = new Object();private static MySingleton instance;public static MySingleton Instance{lock(instanceLock){if(instance == null){instance = new MySingleton();}return instance;}}

使用私有锁对象的lock语句创建一个临界区。要求每个线程等待前一个线程完成。第一个线程将进入该部分并初始化实例。第二个线程将等待,进入该部分并获取初始化的实例。

静态成员的任何类型的同步都可以类似地使用lock语句。

在需要跨多个进程强制对资源进行独占访问的情况下,互斥是有用的,其中常规锁不会有帮助,因为它只能跨线程工作。

要理解MUTEX,首先你需要知道什么是“竞争条件”,然后只有你才能理解为什么需要MUTEX。假设你有一个多线程程序,你有两个线程。现在,作业队列中有一个作业。第一个线程将检查作业队列,找到作业后,它将开始执行它。第二个线程也将检查作业队列,发现队列中只有一个作业。因此,它也将分配相同的作业指针。所以,现在发生的是,两个线程都在执行相同的作业。这将导致分割错误。这是竞争条件的例子。

这个问题的解决方案是MUTEX。MUTEX是一种一次锁定一个线程的锁。如果另一个线程想要锁定它,线程就会被阻塞。

MUTEX主题在这个pdf文件链接非常值得一读。

这里有一些很好的答案,这里有另一个很好的类比来解释互斥锁是什么:

考虑单一厕所有关键。当有人进来时,他们拿走钥匙,厕所是占领。如果其他人需要使用厕所,他们需要在队列等待。当厕所里的人是完成时,他们将钥匙传递给排队的下一个人。有意义,对吧?

将故事中的厕所转换为共享资源,将关键转换为互斥锁。拿着钥匙去厕所(获得一把锁)允许你使用它。如果没有钥匙(锁被锁上了),你必须等待。当钥匙被人(松开锁)归还时,你现在可以自由获得它。

什么是互斥锁

互斥锁(实际上,术语互斥锁是互斥的缩写)也称为自旋锁,是最简单的同步工具,用于保护关键区域从而防止竞争条件。即线程必须在进入临界区之前获得锁(在临界区中,多线程共享一个公共变量,更新表,写入文件等),它在离开临界区时释放锁。

什么是竞赛条件

当两个或多个线程可以访问共享数据并且它们试图同时更改时,就会出现竞争条件。因为线程调度算法可以随时在线程之间交换,你不知道线程将尝试访问共享数据的顺序。因此,数据变化的结果取决于线程调度算法,即两个线程都“竞相”访问/更改数据。

现实生活中的例子:

当我在工作中进行激烈的讨论时,我使用橡皮我把鸡肉放在我的桌子上,只是为了这种场合。这个人拿着鸡是唯一被允许说话的人。如果你不要拿着你不会说话的鸡。你只能表示你想要那只鸡,等到你得到它再说话。一次你已经说完了,你可以把鸡递回主持人将把它交给下一个发言的人。这确保了人们不互相说话,也有自己的说话的空间

用互斥锁和带线程的人替换鸡,你基本上有了互斥锁的概念。

@陈志强

在C#中的用法:

此示例显示了如何使用本地Mutex对象来同步对受保护资源的访问。因为每个调用线程都会被阻塞,直到它获得互斥锁的所有权,所以它必须调用ReleaseMutex方法来释放线程的所有权。

using System;using System.Threading;
class Example{// Create a new Mutex. The creating thread does not own the mutex.private static Mutex mut = new Mutex();private const int numIterations = 1;private const int numThreads = 3;
static void Main(){// Create the threads that will use the protected resource.for(int i = 0; i < numThreads; i++){Thread newThread = new Thread(new ThreadStart(ThreadProc));newThread.Name = String.Format("Thread{0}", i + 1);newThread.Start();}
// The main thread exits, but the application continues to// run until all foreground threads have exited.}
private static void ThreadProc(){for(int i = 0; i < numIterations; i++){UseResource();}}
// This method represents a resource that must be synchronized// so that only one thread at a time can enter.private static void UseResource(){// Wait until it is safe to enter.Console.WriteLine("{0} is requesting the mutex",Thread.CurrentThread.Name);mut.WaitOne();
Console.WriteLine("{0} has entered the protected area",Thread.CurrentThread.Name);
// Place code to access non-reentrant resources here.
// Simulate some work.Thread.Sleep(500);
Console.WriteLine("{0} is leaving the protected area",Thread.CurrentThread.Name);
// Release the Mutex.mut.ReleaseMutex();Console.WriteLine("{0} has released the mutex",Thread.CurrentThread.Name);}}// The example displays output like the following://       Thread1 is requesting the mutex//       Thread2 is requesting the mutex//       Thread1 has entered the protected area//       Thread3 is requesting the mutex//       Thread1 is leaving the protected area//       Thread1 has released the mutex//       Thread3 has entered the protected area//       Thread3 is leaving the protected area//       Thread3 has released the mutex//       Thread2 has entered the protected area//       Thread2 is leaving the protected area//       Thread2 has released the mutex

MSDN参考互斥

Mutex:Mutex的全称是MutualEx,意思是同一时间只有一个进程/进程可以进入临界区。在多线程并发编程时,如果一个线程/进程更新了共享的资源(变量,共享内存等),可能会导致意外的结果。

为了避免这种意想不到的结果,我们需要一些同步机制,确保一次只有一个线程/进程访问这样的资源。

pthreadLibrary提供对Mutex的支持。

typedef union{struct __pthread_mutex_s{***int __lock;***unsigned int __count;int __owner;#ifdef __x86_64__unsigned int __nusers;#endifint __kind;#ifdef __x86_64__short __spins;short __elision;__pthread_list_t __list;# define __PTHREAD_MUTEX_HAVE_PREV      1# define __PTHREAD_SPINS             0, 0#elseunsigned int __nusers;__extension__ union{struct{short __espins;short __elision;# define __spins __elision_data.__espins# define __elision __elision_data.__elision# define __PTHREAD_SPINS         { 0, 0 }} __elision_data;__pthread_slist_t __list;};#endif

这是互斥锁数据类型的结构,即pthread_mutex_t。当互斥锁被锁定时,__lock设置为1。当它被解锁时__lock设置为0。

这确保没有两个进程/线程可以同时访问临界区。