【问题标题】:What happens if a thread is in the critical section or entering the critical section?如果线程处于临界区或进入临界区会怎样?
【发布时间】:2018-11-11 00:06:13
【问题描述】:

我试图更好地理解一章,但对于如果线程处于临界区或正在进入临界区会发生什么感到困惑。有人可以解释或给我一个关于线程在这种情况下经历的过程的想法吗?谢谢你。

【问题讨论】:

    标签: operating-system thread-synchronization


    【解决方案1】:

    举个例子,假设你有一个数组,以及多个读写数组的线程;如果不同的线程同时读取和写入数组,他们会看到不一致的数据,这会导致问题。为了防止这些问题,您可以使用某种锁来保护数组 - 在对数组进行任何操作之前,线程会获取数组的锁,当它完成使用数组时,线程会释放数组的锁。

    例如:

        acquire_array_lock();
        /** Critical section (code that does something with the array) **/
        release_array_lock();
    

    关键部分的代码没有什么特别之处。它使用与您可能用于在单个中执行相同操作的代码没有什么不同的代码执行其设计的任何操作(可能对数组进行排序,可能将数组中的所有数字相加,可能显示数组等) - 没有锁的线程系统。

    唯一特殊的部分是获取和释放锁的代码。

    有许多类型的锁(自旋锁、互斥锁、信号量),但它们都具有相同的基本原理 - 获取它时,您有一些东西(例如变量)来确定线程是否可以/不能继续,然后要么(如果线程不能继续)某种等待,要么(如果线程可以继续)某种改变让其他人知道他们需要等待;并且在释放时,您可以让其他人知道他们可以停止等待。

    不同类型的锁的主要区别在于实现细节——使用什么样的数据来确定线程是否可以继续,以及线程如何等待。

    对于最简单的锁(自旋锁),您可能只有一个“是/否”标志,有点像这样(但实际上不是这样):

    acquire_lock(void) {
        while(myLock == 0) {
            // do nothing then retry
        }
        myLock = 1;
    }
    
    release_lock(void) {
        myLock = 0;
    }
    

    但这不起作用,因为两个或多个线程可以同时看到 myLock == 0 并认为它们都可以继续(然后在为时已晚后执行 myLock = 1)。要解决此问题,您需要汇编语言或对原子操作的特殊语言支持(例如,“测试和设置”或“比较和交换”的特殊功能)。

    这被称为“自旋锁”的原因是(如果线程需要等待)它会浪费 CPU 时间不断检查(“自旋”)以查看它是否可以继续。而不是这样做(以避免浪费 CPU 时间),线程可以告诉调度程序在锁被释放之前不要给它任何 CPU 时间;这就是互斥锁的工作原理。

    【讨论】:

    • 谢谢!但是持有锁的进程可以切换上下文吗?
    • @justoneday:持有锁的任务是否可以切换上下文取决于环境。对于大多数操作系统上的正常任务(线程、进程),任务可以在持有锁的同时进行上下文切换(否则存在恶意代码故意获取锁并且从不释放它以占用所有 CPU 时间的风险)。对于使用自旋锁的内核代码,通常会禁用上下文切换(可能还有 IRQ),以最大限度地减少其他 CPU 花费在自旋上的时间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 2016-10-07
    相关资源
    最近更新 更多