我试图更好地理解一章,并且对于线程在关键部分或正在进入关键部分会发生什么感到困惑。有人可以在这种情况下解释或告诉我有关线程经历的过程吗?谢谢。
答案 0 :(得分:0)
例如,假设您有一个数组,并且有多个线程对该数组进行读写。如果不同的线程同时在读取和写入数组,它们将看到不一致的数据,这会引起问题。为了防止这些问题,您可以使用某种锁来保护数组-在对数组执行任何操作之前,线程会获取数组的锁,并且在使用完数组后,线程会释放数组的锁。
例如:
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时间)。这就是互斥锁的工作方式。