什么是互斥?

时间:2008-08-29 15:59:25

标签: multithreading concurrency mutex

互斥是一种经常用于解决多线程问题的编程概念。我向社区提出的问题:

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

10 个答案:

答案 0 :(得分:1903)

当我在工作中进行激烈的讨论时,我会使用一只橡皮鸡,我会把它留在我的桌子上。持鸡的人是唯一被允许说话的人。如果你不抓鸡,你就不会说话。你只能表明你想要鸡肉并等到你说话之前就得到它。讲完后,你可以把鸡还给主持人,主持人会把它交给下一个发言的人。这可以确保人们不会互相交谈,也有自己的谈话空间。

用Mutex替换Chicken和有线程的人,你基本上都有互斥的概念。

当然,没有橡皮互补器这样的东西。只有橡皮鸡。我的猫曾经有一只橡皮鼠,但他们吃了它。

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

答案 1 :(得分:110)

Mutex是互斥旗帜。它充当一段代码的守门员,允许一个线程进入并阻止访问所有其他线程。这可以确保所控制的代码一次只能被一个线程命中。确保在完成后释放互斥锁。 :)

答案 2 :(得分:65)

相互排斥。这是维基百科上的条目:

http://en.wikipedia.org/wiki/Mutual_exclusion

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

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

答案 3 :(得分:44)

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

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

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

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

现在,请问google如何使用它们! :)

答案 4 :(得分:26)

在C#中,使用的常用互斥锁是Monitor。类型为“System.Threading.Monitor”。它也可以通过'lock(Object)'语句隐式使用。其用法的一个例子是构造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语句。

答案 5 :(得分:15)

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

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

MUTEX主题in this pdf file链接非常值得一读。

答案 6 :(得分:14)

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

使用考虑厕所。当有人进入时,他们拿钥匙,厕所占用。如果其他人需要使用厕所,他们需要在队列中等待。当厕所中的人完成时,他们将密钥传递给队列中的下一个人。有道理,对吧?

将故事中的厕所转换为共享资源,将密钥转换为互斥。将钥匙带到马桶上(获得锁)允许您使用它。如果没有钥匙(锁被锁定),你必须等待。当人员返回密钥(释放锁)时,您现在可以自由获取密钥。

答案 7 :(得分:13)

什么是Mutex

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

什么是Race Condition

当两个或多个线程可以访问共享数据并且他们试图同时更改它们时,就会发生竞争状态。因为线程调度算法可以随时在线程之间交换,所以您不知道线程尝试访问共享数据的顺序。因此,数据更改的结果取决于线程调度算法,即两个线程都在“竞争”以访问/更改数据。

现实生活中的示例:

  

当我在工作中进行激烈讨论时,我会使用橡胶   我只把鸡放在这样的场合。此人   拿着鸡是唯一被允许说话的人。如果你   不要握住你不会说话的鸡。您只能指出   您想要这只鸡,然后等到收到它再说。一旦   你说完了,可以把鸡递回去   主持人将把它交给下一个说话的人。这样可以确保   人们不会互相说话,也有自己的声音   聊天的空间。

     

用Mutex和带有线程的人替换Chicken,您基本上具有互斥量的概念。

     

@Xetius

在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 Reference Mutex

答案 8 :(得分:11)

在需要对多个进程中的资源强制执行独占访问的情况下,互斥锁非常有用,常规锁定无法帮助,因为它只能在线程上运行。

答案 9 :(得分:2)

Mutex:Mutex代表 Mut 共有的 Ex 包含。这意味着在给定的时间只有一个进程/线程可以进入关键部分。在并发编程中,多个线程/进程更新共享资源(任何变量,共享内存等)可能会导致某些意外结果。 (结果取决于哪个线程/进程获得首次访问权。)

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

pthread库提供对Mutex的支持。

typedef union
{
  struct __pthread_mutex_s
  {
    ***int __lock;***
    unsigned int __count;
    int __owner;
#ifdef __x86_64__
    unsigned int __nusers;
#endif
int __kind;
#ifdef __x86_64__
    short __spins;
    short __elision;
    __pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV      1
# define __PTHREAD_SPINS             0, 0
#else
    unsigned 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。

这确保没有两个进程/线程可以同时访问关键部分。