• 欢迎光临~

操作系统导论习题解答(26. Concurrency and Threads)

开发技术 开发技术 2022-10-14 次浏览

Concurrency: An Introduction

我们这里引入了thread(线程)的概念,与前面所说process(进程)的区别如下:

  1. 线程之间进行上下文切换地址空间保持不变。
  2. 每个线程都将有一个stack。

操作系统导论习题解答(26. Concurrency and Threads)

1. Why Use Threads?

在深入了解thread之前,首先需要知道为什么要使用thread。至少有如下两个原因:

  1. parallelism
  2. to avoid blocking program progress due to slow I/O

上述两个原因你也可以使用多进程,但是线程共享一个地址空间,因此很容易共享数据,因此在构造这些类型的程序时多线程是很好的一个选择。对于在内存中几乎不需要共享数据结构的逻辑上独立的任务而言,多进程是一个更合理的选择。

2. An Example: Thread Creation

操作系统导论习题解答(26. Concurrency and Threads)
下图线程运行顺序不是唯一顺序
操作系统导论习题解答(26. Concurrency and Threads)
下图所示一种情况,当线程被创造出来后就直接运行
操作系统导论习题解答(26. Concurrency and Threads)
线程创造后如何运行取决于scheduler,它要是喜欢,“B”也可以在"A"前面打印出来。如下所示

操作系统导论习题解答(26. Concurrency and Threads)
不过,引入了并发使得计算机变得更糟糕!

3. Why It Gets Worse: Shared Data

接下来谈谈线程在访问共享数据时如何交互。

操作系统导论习题解答(26. Concurrency and Threads)
看一下上面的代码,最终counter的结果应该为2e7。期望的汇编结果如下:
操作系统导论习题解答(26. Concurrency and Threads)
但是,即使在单个处理器的机器上运行此代码都无法得到期望的结果:
操作系统导论习题解答(26. Concurrency and Threads)
操作系统导论习题解答(26. Concurrency and Threads)
为什么不能得到期望的结果呢?
操作系统导论习题解答(26. Concurrency and Threads)

4. The Heart Of The Problem: Uncontrolled Scheduling

为了理解为什么上述情况发生,我们就必须理解汇编器如何对counter进行更新。
假设counter地址为0x8049a1c,对其更新的汇编代码如下所示:

mov 0x8049a1c, %eax
add $0x1, %eax
mov %eax, 0x8049a1c

假设eax当前的值为50,线程1执行上述三条语句,当执行完前两条语句后,进程转换发生了,系统准备运行线程2。这时,线程1中的eax的值为51被保存起来,线程2开始运行上述三条语句,但是此时eax的值还是50,线程2执行完三条语句后eax的值为51。然后转换到线程1进行执行,但是此时对于线程1来说,它取出被保存的eax值,然后执行最后一条语句。简而言之就是:eax的值应该加2,但是最终的eax的值只加了1。这样,就产生了上述非理想情况。

下图所示可以更好地理解
操作系统导论习题解答(26. Concurrency and Threads)

5. The Wish For Atomicity

解决上述问题的方法就是使用更强大的指令,只需一部即可完全完成我们需要做的一切,从而消除了不及时中断的可能性。

程序员灯塔
转载请注明原文链接:操作系统导论习题解答(26. Concurrency and Threads)
喜欢 (0)