gpt4 book ai didi

multithreading - 线程: When ones thread is running can you interact with the other?

转载 作者:行者123 更新时间:2023-12-03 13:15:05 26 4
gpt4 key购买 nike

因此,我目前正在学习线程,并且想知道如何处理某些事情。例如,假设我有一个程序,其中一个线程监听输入,另一个线程在单个处理器上执行一些计算。当计算线程正在运行时,如果用户应按下用于输入线程的按钮会怎样?在切换到特定线程之前,输入线程不会忽略输入吗?

最佳答案

这很大程度上取决于输入机制的实现方式。实现I/O的一种简单但非常模糊的方法是连续轮询...在这种情况下,输入线程可能处于循环中,一遍又一遍地读取硬件寄存器,并且当寄存器中的值更改时从0到1,输入线程将知道该按钮已被按下:

void inputThread()
{
while(1)
{
if (some_register_indicates_the_button_is_pressed()) react();
}
}

这种方法的问题是效率极低-输入线程正在使用数十亿个CPU周期,只是一遍又一遍地检查寄存器。在运行此代码的多线程系统中,线程调度程序将每量子(例如,每10毫秒一次)在忙于等待的输入线程和计算线程之间切换CPU,因此输入线程将使用一半的CPU周期和计算线程将使用另一半。在此系统中,如果在用户按下按钮的那一刻输入线程正在运行,则几乎可以立即检测到输入,但是如果计算线程在运行,则直到下一次输入线程被检测到,输入才被检测到。运行,因此可能会有多达10mS的延迟。 (更糟糕的是,如果用户过早释放按钮,则输入线程可能根本不会注意到它被按下了)

计划轮询是对连续轮询的一项改进。它的工作原理与上述相同,除了它不是输入线程只是在循环中轮询外,它轮询一次,然后休眠一会儿,然后再次轮询:
void inputThread()
{
while(1)
{
if (some_register_indicates_the_button_is_pressed()) react();
usleep(3000); // sleep for 30 milliseconds
}
}

与第一种情况相比,这种方法的效率要低得多,因为每次调用usleep()时,线程调度程序都会将输入线程置于 sleep 状态,并使CPU立即可供其他任何线程使用。 usleep()还会设置一个硬件计时器,当该硬件计时器关闭(30毫秒后)时,它将引发一个中断。中断导致CPU放弃正在执行的操作,然后再次运行线程调度代码,并且线程调度代码将(在大多数情况下)意识到usleep()返回的时间并唤醒输入线程。因此它可以对其循环进行另一次迭代。这仍然不是完美的:inputThread仍在持续使用少量的CPU-数量不多,但是如果您执行许多此操作,它将开始累加。同样,线程在整个按下期间一直处于 sleep 状态的问题仍然存在,甚至有可能更多。

这导致我们进入中断驱动的I/O。在此模型中,输入线程根本不轮询;相反,它告诉操作系统在按下按钮时通知它:
void inputThread()
{
while(1)
{
sleep_until_button_is_pressed();
react();
}
}

反过来,操作系统的通知功能必须进行设置,以便在按下按钮时通知操作系统,以便操作系统可以唤醒并通知输入线程。操作系统通过告诉按钮的控制硬件在按下按钮时产生中断来完成此操作。一旦该中断消失,它的工作原理与上一示例中的计时器中断非常相似; CPU运行线程调度程序代码,该代码可以唤醒该输入线程,并让输入线程运行。该机制具有非常好的特性:(1)按下按钮时,输入线程会尽快唤醒(无需等待计算线程首先完成其量子运算),以及(2)输入线程不会耗尽除了按下按钮时以外,所有CPU周期都不会。由于这些优点,现代计算机将这种机制用于任何非平凡的I/O。

请注意,在现代PC或Mac上,除了两个线程和一个硬件按钮外,还需要进行更多的工作。例如一次运行着数十种硬件设备(键盘,鼠标,视频卡,硬盘驱动器,网卡,声卡等)和数十种程序,操作系统的工作是在必要时在它们之间进行中介。尽管如此,一般原则仍然相同。假设在您的示例中,用户单击的按钮不是物理按钮,而是屏幕上的GUI按钮。在这种情况下,将发生类似以下事件序列的事件:
  • 用户的手指按下鼠标左键
  • 鼠标的内部硬件通过USB电缆将鼠标按下的消息发送到计算机的USB Controller
  • 计算机的USB Controller 生成一个中断
  • 中断导致CPU脱离计算线程的代码并运行OS的调度程序例程
  • 线程调度程序发现USB中断行指示USB事件已准备就绪,并通过运行USB驱动程序的中断处理程序代码
  • 进行响应
  • USB驱动程序的中断处理程序代码在事件中读取,看到它是鼠标按下事件,并将其传递给窗口管理器
  • 窗口管理器知道哪个窗口具有焦点,因此它知道哪个程序将鼠标按下事件转发给
  • 窗口管理器告诉操作系统唤醒与该窗口关联的输入线程
  • 您的输入线程将唤醒并调用react()
  • 关于multithreading - 线程: When ones thread is running can you interact with the other?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14790018/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com