C 事件的有信号和无信号状态
这对所有人来说都可能是一个非编程问题,我确实读到了线程同步对象,比如事件,以及如何将其设置为有信号或无信号状态。然而,我无法理解这些术语,有信号的和无信号的。每一个都以不同的方式表达,我有点困惑C 事件的有信号和无信号状态,c,multithreading,winapi,C,Multithreading,Winapi,这对所有人来说都可能是一个非编程问题,我确实读到了线程同步对象,比如事件,以及如何将其设置为有信号或无信号状态。然而,我无法理解这些术语,有信号的和无信号的。每一个都以不同的方式表达,我有点困惑 声明 有信号的状态表示资源可供进程或线程使用。无信号状态表示资源正在使用中 我从一个大学网站上得到了一个power point演示,上面说 处于信号状态的对象不会导致等待该对象的线程阻塞,而不处于信号状态的对象会导致等待该对象的任何线程阻塞,直到该对象再次发出信号 声明 事件处于信号状态意味着它有能
用一个例子简单解释一下这个概念会很有帮助。好的,你的三个引号并不矛盾。但让我们深入到实现方面: 每个可等待对象都附加了一个布尔值,称为信号状态,用于等待该对象;如果对象发出信号,则等待功能将不等待它;如果对象没有信号,则等待功能将等待它 现在,这如何应用于特定类型的对象?这取决于对象的性质,特别是与等待相关的语义。实际上,信号状态是根据等待条件定义的。例如(有关详细信息,请参见文档):
- 当互斥对象不属于自己时,会发出信号
- 进程/线程完成后会发出信号
- 信号量的计数大于0时发出信号
- 等待计时器过期时发出信号
- 发出信号:线程不会等待它
- 无信号:线程将等待它
SignalPulse
和AutoReset
事情(IME实际上不可能正确使用)
现在,让我们看一下您的报价:
有信号的状态表示资源可供进程或线程使用。无信号状态表示资源正在使用中
实际上,这是一种解释。通常,您试图仲裁某个资源,并且通常仅当该资源正在使用时您才会等待,因此这是在使用中的资源和等待资源之间建立等价关系。但这不是一个技术要求,只是一个常见的用例
处于信号状态的对象不会导致等待该对象的线程阻塞,而不处于信号状态的对象会导致等待该对象的任何线程阻塞,直到该对象再次发出信号
正确且切中要害
事件处于信号状态意味着它有能力释放等待该事件信号的线程。事件处于无信号状态意味着它不会释放任何正在等待此特定事件的线程
我觉得这个措词有点令人困惑。。。但它没有比前一个解释增加任何内容。事实上,所有这些解释都是一致的 对事件最简单(因此不是100%准确)的解释是将事件视为操作系统提供的一种标志服务。有信号的事件可以看作是一个设置标志,而无信号的事件则可以看作是一个未设置标志 为了实现基于标志的生产者/消费者线程系统,通常会执行以下操作(注意,为了简单起见,我忽略了进一步的同步机制): 不幸的是,这将导致在繁忙等待循环中浪费处理器周期,或者由于引入
Sleep
调用以降低CPU消耗而导致不必要的执行延迟。两者都是多余的
为了避免任务同步出现此类问题,操作系统提供了不同的类似于标志的机制(例如Windows中的事件)。对于事件,设置和重置标志由操作系统调用SetEvent
/ResetEvent
完成。要检查标志,可以使用WaitForSingleObject
。此调用有能力将任务置于休眠状态,直到事件发出信号,这在CPU消耗方面是最佳的
这将上述示例转化为如下内容:
static volatile char data = 'A';
static HANDLE newDataEvent = INVALID_HANDLE_VALUE;
// Some code to initialize the threads and the newDataEvent handle
void producer()
{
while (1)
{
Sleep(1000);
data++;
SetEvent(newDataEvent);
}
}
void consumer()
{
while (1)
{
if (WaitForSingleObject(newDataEvent, INFINITE) == WAIT_OBJECT_0)
{
ResetEvent(newDataEvent);
// process data
}
}
}
简单的思考方式:“信号灯”=“绿灯” 发出信号: 如果您在驾驶时看到绿灯,您不会停车(这是一个线程正在查看一个事件,发现它发出了信号,并且在没有阻塞的情况下继续) 无信号:
如果你看到红灯,你会停下来,等待红灯变绿,然后继续(据我所知,其他线程现在都没有信号,因此正在等待或将在红灯处等待!)我不同意其他答案。他们没有抓住要点:
- 如果信号属性为真=>则事件发生在之前
- 如果发出信号的属性为false,则事件没有发生
static volatile char data = 'A'; static HANDLE newDataEvent = INVALID_HANDLE_VALUE; // Some code to initialize the threads and the newDataEvent handle void producer() { while (1) { Sleep(1000); data++; SetEvent(newDataEvent); } } void consumer() { while (1) { if (WaitForSingleObject(newDataEvent, INFINITE) == WAIT_OBJECT_0) { ResetEvent(newDataEvent); // process data } } }