我们为什么需要信号量,条件变量和其他构造。我得到一个线程被阻塞,直到信号好于需要互斥锁的线程,然后检查是否通过的 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)我可以说多线程中的所有操作都可以只使用互斥锁吗?
答案 0 :(得分:0)
互斥锁旨在为线程之间的共享变量提供保护,而并非旨在提供同步。
我会举一个例子,假设我们有一个需要共享的链表,我们需要旋转10个线程-其中5个线程负责写链表,另外5个线程负责从链表中读取。 我们必须将链接列表视为队列(FIFO)-写入列表的末尾,从列表的前部读取 所有线程都需要对链接列表的独占访问权限(因为当写程序添加到队列的末尾时读者会从队列的开头删除项目),并且对计算有随机的延迟(或者只是假设他们需要睡觉) 现在的问题:我们如何确保队列的头和尾的完整性?
仅使用互斥锁似乎不可能吗? 这就是为什么NO,互斥量在所有情况下都不够的原因。
就我而言,我们需要一个条件变量 使用这些变量并通过广播(甚至单独通知)通知其他线程,我们将能够实现线程之间的同步,从而确保我们共享的头和脚的完整性。
PS:另一个不错的观点 is this. PS
答案 1 :(得分:0)
关于,“我们为什么需要...构造?”
因为layers of abstraction和code reuse。
例如,您不需要具有阻塞队列。如果您有数组,指针,互斥体和条件变量,则可以使用它们来实现可以使用阻塞队列实现的任何东西。但是您的代码很难阅读,因为在您可能刚刚调用过q.put(...)
或q.take()
的每个地方,您将不得不编写一整行代码。
阻塞队列是一种有用的抽象:它将较低层的构想包装成一个更简单的较高层的函数。
如果您有阻塞队列,则不需要 信号灯。您可以使用信号量执行任何操作,方法是将无意义的令牌放入队列中,然后将其删除。信号量确实是队列思想的简单版本,它可能更适合(您可以更好地描述)您要解决的问题。
此外,您不需要使用任何其他人执行的阻塞队列或信号量的实现:您可以始终编写自己的代码,但是为什么要这样做呢? (除非是出于教育目的。)