为什么互斥体还不够?

时间:2018-08-24 09:59:47

标签: multithreading pthreads mutex semaphore readerwriterlock

我们为什么需要信号量条件变量和其他构造。我得到一个线程被阻塞,直到信号好于需要互斥锁的线程,然后检查是否通过的 condition 条件,然后解锁并重试直到条件通过。
除此之外,还有其他好处。 例如,我们可以仅使用 mutex 来实现读写锁定吗? 如下所示:

int writers = 0;
int readers = 0;
mutex lock;

read_lock()
{
    mutex_lock(&lock);
    while(writers == 1)
    {
        mutex_unlock(&lock);  // unlock
        mutex_lock(&lock);    // retry
    }
    readers++;
    mutex_unlock(&lock);    
}

read_unlock()
{
    mutex_lock(&lock);
    readers--;
    mutex_unlock(&lock);
}

write_lock()
{
    mutex_lock(&lock);
    while(r>0 || w==1)
    {
        mutex_unlock(&lock);  // unlock
        mutex_lock(&lock);    // retry
    }
    writers++;
    mutex_unlock(&lock);      
}

write_unlock()
{
    mutex_lock(&lock);
    writers--;
    mutex_unlock(&lock);
}

1)上面的实现是否还能起作用?如果没有,为什么?
2)我可以说多线程中的所有操作都可以只使用互斥锁吗?

2 个答案:

答案 0 :(得分:0)

互斥锁旨在为线程之间的共享变量提供保护,而并非旨在提供同步。

我会举一个例子,假设我们有一个需要共享的链表,我们需要旋转10个线程-其中5个线程负责写链表,另外5个线程负责从链表中读取。 我们必须将链接列表视为队列(FIFO)-写入列表的末尾,从列表的前部读取 所有线程都需要对链接列表的独占访问权限(因为当写程序添加到队列的末尾时读者会从队列的开头删除项目),并且对计算有随机的延迟(或者只是假设他们需要睡觉)  现在的问题:我们如何确保队列的头和尾的完整性?

仅使用互斥锁似乎不可能吗? 这就是为什么NO,互斥量在所有情况下都不够的原因。

就我而言,我们需要一个条件变量 使用这些变量并通过广播(甚至单独通知)通知其他线程,我们将能够实现线程之间的同步,从而确保我们共享的头和脚的完整性。

PS:另一个不错的观点 is this. PS

答案 1 :(得分:0)

  

关于,“我们为什么需要...构造?”

因为layers of abstractioncode reuse

例如,您不需要具有阻塞队列。如果您有数组,指针,互斥体和条件变量,则可以使用它们来实现可以使用阻塞队列实现的任何东西。但是您的代码很难阅读,因为在您可能刚刚调用过q.put(...)q.take()的每个地方,您将不得不编写一整行代码。

阻塞队列是一种有用的抽象:它将较低层的构想包装成一个更简单的较高层的函数。

如果您有阻塞队列,则不需要 信号灯。您可以使用信号量执行任何操作,方法是将无意义的令牌放入队列中,然后将其删除。信号量确实是队列思想的简单版本,它可能更适合(您可以更好地描述)您要解决的问题。

此外,您不需要使用任何其他人执行的阻塞队列或信号量的实现:您可以始终编写自己的代码,但是为什么要这样做呢? (除非是出于教育目的。)