Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 当线程两次尝试获取同一个自旋锁时,为什么会出现死锁?_Multithreading_Spinlock - Fatal编程技术网

Multithreading 当线程两次尝试获取同一个自旋锁时,为什么会出现死锁?

Multithreading 当线程两次尝试获取同一个自旋锁时,为什么会出现死锁?,multithreading,spinlock,Multithreading,Spinlock,有人能解释一下为什么当一个线程尝试两次抓取同一个自旋锁时会出现死锁吗?假设自旋锁是非递归的 常规自旋锁用法: lock = false; while(acquiring_lock(lock)) {} //sit in the loop and wait for lock to become available ....critical section.... release_lock(lock); 然而,我不明白为什么第二次调用locklock会导致死锁?这个问题似乎真的取决于所讨论的线

有人能解释一下为什么当一个线程尝试两次抓取同一个自旋锁时会出现死锁吗?假设自旋锁是非递归的

常规自旋锁用法:

lock = false; 
while(acquiring_lock(lock)) {} //sit in the loop and wait for lock to become available
....critical section....
release_lock(lock);  

然而,我不明白为什么第二次调用locklock会导致死锁?

这个问题似乎真的取决于所讨论的线程库,以及不同函数的规范。所以,让我们考虑一些可能性。

锁定机制可以是非阻塞机制,也可以是非重入机制

/** 
* This function performs a busy wait, blocking until it acquires the lock
* This is not re-entrant.
**/
void blocking_acquire_lock(bool thingToLock);
如果尝试使用前面的函数,代码将死锁。这是因为线程在获得锁之前不会继续执行。您不会在while循环的条件位置使用它,因为它不会返回bool。其次,它不是可重入的,这意味着即使在使用同一线程获得锁之后,如果您尝试重新获取锁,它也会继续等待释放锁

/** 
* This function performs a non-blocking busy wait, blocking for up to X milleseconds, 
* until it acquires the lock. This is not re-entrant.
* returns true if lock acquired, false if lock not acquired
**/
bool non_blocking_acquire_lock(bool thingToLock, int timeoutInMilliseconds);
这个版本在while循环中使用是有意义的。您可以尝试获取一个锁,但如果它在分配的时间内没有成功,您可以决定做什么。也许,你会决定做一段时间的其他事情,然后重新尝试获取锁

因为它不是可重入的,所以它不允许同一线程在不首先释放它的情况下获取它两次。因此,您的代码将死锁

这里是最后一个似乎会使代码死锁的示例

/** 
* This function performs a non-blocking busy wait, blocking for up to X milleseconds, 
* until it acquires the lock. This is re-entrant.
* returns true if lock acquired, false if lock not acquired
**/
bool non_blocking_reentrant_acquire_lock(bool thingToLock, int timeoutInMilliseconds);
此锁是可重入的,因此如果线程拥有该锁,它可以重新获取该锁。但是,如果您像下面这样在while循环中使用这个函数,您会注意到一些有趣的事情

my_lock = false; 
while(acquiring_lock(my_lock, 1000)) { ; }
    ....critical section....
release_lock(lock);  
由于如果锁在1秒内获得锁,则返回true,并且这是唯一的线程,因此它很可能会毫无问题地获得锁。这是真的。在这种情况下,它将保持在while循环中。while循环为空,因此它会立即尝试重新获取锁

由于它是重新进入的,我希望它能继续成功。它将继续成功地重新获取锁,并且永远不会通过while循环

我希望下面的代码有一个额外的!做你想做的事

my_lock = false; 
while( !acquiring_lock(my_lock, 1000)) { ; }
    ....critical section....
release_lock(lock);  

此版本在获得锁后,实际上将停止尝试获取锁,即退出while循环。

似乎此问题实际上取决于所讨论的线程库以及不同函数的规范。所以,让我们考虑一些可能性。

锁定机制可以是非阻塞机制,也可以是非重入机制

/** 
* This function performs a busy wait, blocking until it acquires the lock
* This is not re-entrant.
**/
void blocking_acquire_lock(bool thingToLock);
如果尝试使用前面的函数,代码将死锁。这是因为线程在获得锁之前不会继续执行。您不会在while循环的条件位置使用它,因为它不会返回bool。其次,它不是可重入的,这意味着即使在使用同一线程获得锁之后,如果您尝试重新获取锁,它也会继续等待释放锁

/** 
* This function performs a non-blocking busy wait, blocking for up to X milleseconds, 
* until it acquires the lock. This is not re-entrant.
* returns true if lock acquired, false if lock not acquired
**/
bool non_blocking_acquire_lock(bool thingToLock, int timeoutInMilliseconds);
这个版本在while循环中使用是有意义的。您可以尝试获取一个锁,但如果它在分配的时间内没有成功,您可以决定做什么。也许,你会决定做一段时间的其他事情,然后重新尝试获取锁

因为它不是可重入的,所以它不允许同一线程在不首先释放它的情况下获取它两次。因此,您的代码将死锁

这里是最后一个似乎会使代码死锁的示例

/** 
* This function performs a non-blocking busy wait, blocking for up to X milleseconds, 
* until it acquires the lock. This is re-entrant.
* returns true if lock acquired, false if lock not acquired
**/
bool non_blocking_reentrant_acquire_lock(bool thingToLock, int timeoutInMilliseconds);
此锁是可重入的,因此如果线程拥有该锁,它可以重新获取该锁。但是,如果您像下面这样在while循环中使用这个函数,您会注意到一些有趣的事情

my_lock = false; 
while(acquiring_lock(my_lock, 1000)) { ; }
    ....critical section....
release_lock(lock);  
由于如果锁在1秒内获得锁,则返回true,并且这是唯一的线程,因此它很可能会毫无问题地获得锁。这是真的。在这种情况下,它将保持在while循环中。while循环为空,因此它会立即尝试重新获取锁

由于它是重新进入的,我希望它能继续成功。它将继续成功地重新获取锁,并且永远不会通过while循环

我希望下面的代码有一个额外的!做你想做的事

my_lock = false; 
while( !acquiring_lock(my_lock, 1000)) { ; }
    ....critical section....
release_lock(lock);  

此版本在获得锁后实际上将停止尝试获取锁,即退出while循环。

很难猜测您使用的是哪种线程库。但是如果出现死锁,那么常见的诊断是锁不是可重入的。“这并不奇怪,”汉帕桑说,“这只是一个理论问题。不过,我明白你的意思,我会纠正这个问题:获取锁定功能的规范是什么?如果获取了锁,它会返回true吗?还是会返回错误?它会一直阻塞直到获得锁吗?@Xantix因为我对多任务处理还不熟悉,所以我假设它会被阻塞
意味着在互斥的情况下它将只是等待-进入睡眠状态,如果它是非阻塞自旋锁,它将返回1或0?谢谢很难猜测您使用的是哪种线程库。但是如果出现死锁,那么常见的诊断是锁不是可重入的。“这并不奇怪,”汉帕桑说,“这只是一个理论问题。不过,我明白你的意思,我会纠正这个问题:获取锁定功能的规范是什么?如果获取了锁,它会返回true吗?还是会返回错误?它会一直阻塞直到获得锁吗?@Xantix因为我对多任务处理是新手,我假设阻塞意味着它将在互斥情况下等待-进入睡眠状态,如果它是非阻塞自旋锁,它将返回1或0?谢谢哇!谢谢你花时间向我解释这一切。哇!!!谢谢你花时间向我解释这一切。