关键部分与计数信号量有什么关系?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关键部分与计数信号量有什么关系?相关的知识,希望对你有一定的参考价值。

Some people说你应该使用互斥锁来保护共享资源(即关键部分),而信号量应该用于信令,而不是反之亦然。所以,据我所知,信号量与关键部分无关。

然而,许多其他文章,包括Wikipedia声称信号量用于解决临界区问题。说二进制信号量解决关键部分问题实际上更正确,因为它们基本上像互斥体一样,而计算信号量是一个不同的东西而不属于“资源保护者”类别?

答案

计数信号量可用于资源保护,但它们通常以与互斥信号量不同的方式用于不同的资源。

典型的例子是队列。对于动态大小的队列,您有一个计算的信号量来跟踪队列中当前有多少项。消费者等待该信号量告诉他们何时可以从队列中读取项目。

对于固定大小的队列,您可以添加第二个计算的信号量,以跟踪队列中的空白空间量。作家等待它确定何时允许他们将项目推送到队列。

您经常使用互斥信号量与这些信号量相结合,以确保在任何给定时间只有一个线程修改队列本身。

例如,以下是使用Win32计数信号量(和互斥锁)的固定大小队列的一些代码:

#ifndef QUEUE_H_INCLUDED
#define QUEUE_H_INCLUDED

#include <windows.h>

template<class T, unsigned max = 256>
class queue { 
    HANDLE space_avail; // at least one slot empty
    HANDLE data_avail;  // at least one slot full
    CRITICAL_SECTION mutex; // protect buffer, in_pos, out_pos

    T buffer[max];
    long in_pos, out_pos;
public:
    queue() : in_pos(0), out_pos(0) { 
        space_avail = CreateSemaphore(NULL, max, max, NULL);
        data_avail = CreateSemaphore(NULL, 0, max, NULL);
        InitializeCriticalSection(&mutex);
    }

    void push(T data) { 
        WaitForSingleObject(space_avail, INFINITE);       
        EnterCriticalSection(&mutex);
        buffer[in_pos] = data;
        in_pos = (in_pos + 1) % max;
        LeaveCriticalSection(&mutex);
        ReleaseSemaphore(data_avail, 1, NULL);
    }

    T pop() { 
        WaitForSingleObject(data_avail,INFINITE);
        EnterCriticalSection(&mutex);
        T retval = buffer[out_pos];
        out_pos = (out_pos + 1) % max;
        LeaveCriticalSection(&mutex);
        ReleaseSemaphore(space_avail, 1, NULL);
        return retval;
    }

    ~queue() { 
        DeleteCriticalSection(&mutex);
        CloseHandle(data_avail);
        CloseHandle(space_avail);
    }
};

#endif

以上是关于关键部分与计数信号量有什么关系?的主要内容,如果未能解决你的问题,请参考以下文章

信号量与互斥锁的区别

揭秘 Python 中的 with 关键字

什么是线程中的关键部分

关键部分:多个阅读器,单个作者

信号量的基本概念与使用semget,semop

信号量 - 初始计数有啥用?