首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >事件的信号和非信号状态

事件的信号和非信号状态
EN

Stack Overflow用户
提问于 2013-07-12 10:55:48
回答 4查看 11K关注 0票数 13

对于所有人来说,这可能是一个非编程问题,我确实读过一些关于线程同步对象(如event )的文章,以及如何将其设置为信号状态或非信号状态。然而,我无法理解这些术语,发出信号,没有信号,,.Each,one以不同的方式表达,我有点困惑。

  1. This link说 发出信号的状态指示资源可供进程或线程使用。未发出信号的状态指示正在使用的资源。

  1. 我从一所大学的网站上得到了一个关于力量点的报告 处于信号状态的对象不会导致等待对象的线程阻塞,而处于信号状态的对象将导致等待该对象的任何线程阻塞,直到该对象再次发出信号为止。

  1. This third link声明如下 事件处于信号状态,意味着它有能力释放等待此事件被发送信号的线程。事件处于无信号状态,意味着它不会释放等待此特定事件的任何线程。

用一个例子简单地解释一下这个概念将是非常有帮助的。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-07-12 11:19:25

好吧,你的三个引号不是不兼容的。但是,让我们深入讨论一下实现:

每个可等待对象都附加了一个布尔值,名为信号状态,用于等待该对象;如果该对象被发送信号,则等待函数将而不是等待它;如果该对象没有信号,则等待函数将对其进行等待。

现在,这如何应用于特定类型的对象?这取决于对象的性质,特别是与等待对象相关的语义。实际上,信号状态是用等待条件来定义的。例如(有关详细信息,请参阅文档):

  • 互斥对象在未被拥有时会发出信号。
  • 进程/线程完成后会发出信号。
  • 当信号量大于0时,就会发出信号。
  • 等待计时器过期时会发出信号。

如果一个互斥在拥有时发出信号,你可能会更喜欢,但实际上它是在不拥有的时候。这对于让等待函数做正确的事情是必要的。

那这些事件呢?嗯,它们是一些简单的对象,您可以随意发送信号和去信号,因此信号状态没有额外的含义:

  • 提示:线程不会等待它。
  • 没有信号:线程会等待它。

事件也有一些特殊的SignalPulseAutoReset (而且IME几乎不可能正确使用)。

现在,让我们看看你的引语:

发出信号的状态指示资源可供进程或线程使用。未发出信号的状态指示正在使用的资源。

实际上,这是一种解释。通常有一个资源你在试图仲裁,通常你等待如果和唯一-如果该资源正在使用,所以它是在资源使用和等待资源之间的等价。但这不是技术要求,只是一个常用的用例。

处于信号状态的对象不会导致等待对象的线程阻塞,而处于信号状态的对象将导致等待该对象的任何线程阻塞,直到该对象再次发出信号为止。

正确,切中要害!

事件处于信号状态,意味着它有能力释放等待此事件被发送信号的线程。事件处于无信号状态,意味着它不会释放等待此特定事件的任何线程。

我觉得这个措辞有点混乱..。但它并没有比前一个增加任何东西。

票数 24
EN

Stack Overflow用户

发布于 2013-07-12 13:24:29

简单的想法:“信号”=“绿灯”

发出信号:如果您正在开车,看到了绿灯,您就不会停下来(这是查看事件的线程,发现是发出了信号,并且没有阻塞地继续进行)。

Non-Signalled:,如果你看到红灯,你就停下来,等它变绿,然后继续(安全地知道,其他线程现在都没有信号了,因此正在等待或将在their...red灯前等待!)

票数 18
EN

Stack Overflow用户

发布于 2013-07-12 11:23:17

事实上,所有这些解释都是一致的。

对事件的最简化(因此不是100%准确)解释是将事件看作是操作系统提供的一种标志服务。信号事件可以看作是一个集合标志,而一个没有信号的事件则可以看作是一个未设置的标志。

为了实现基于标志的生产者/使用者线程系统,您通常执行如下操作(为了简单起见,我忽略了进一步的同步机制):

代码语言:javascript
复制
static volatile int  flag = 0;
static volatile char data = 'A';

// Some code to initialize the threads  

void producer()
{
    while (1)
    {
        Sleep(1000);
        data++;
        flag = 1;
    }
}

void consumer()
{
    while (1)
    {
        /* Busy wait for the occurence of more data */
        while (!flag)
        {
            // wait for next data
        }

        flag = 0;

        // process data
    }
}

不幸的是,这将导致在繁忙的等待循环中浪费处理器周期,或者由于引入Sleep调用以降低CPU消耗而导致不必要的执行延迟。两者都是多余的。

为了避免任务同步出现这样的问题,操作系统提供了不同的类似标记的机制(例如Windows中的事件)。对于事件,通过OS调用SetEvent/ResetEvent来设置和重置标志。若要检查标志,可以使用WaitForSingleObject。这个调用可以让任务进入休眠状态,直到事件得到信号为止,这在CPU消耗方面是最优的。

这会将上面的示例转换为如下所示:

代码语言:javascript
复制
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
        }
    }
}
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17613342

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档