我在Linux上使用读/写锁,并且我发现试图将读锁对象升级为写锁死锁。
即
// acquire the read lock in thread 1.
pthread_rwlock_rdlock( &lock );
// make a decision to upgrade the lock in threads 1.
pthread_rwlock_wrlock( &lock ); // this deadlocks as already hold read lock.我读过手册页,它很具体。
调用线程如果在调用时持有读-写锁(无论是读锁还是写锁),则可能会死锁。
在这种情况下,将读锁升级为写锁的最佳方法是什么?我不想在我保护的变量上引入种族。
想必我可以创建另一个互斥锁,包括释放读锁和获取写锁,但我没有真正看到读/写锁的使用。我也可以简单地使用一个普通的互斥。
Thx
发布于 2010-03-09 08:53:09
在下面的场景中,除了死锁之外,您还想要什么?
因此,我只需要释放读锁,获取写锁,然后再次检查是否需要进行更新。
发布于 2019-03-31 22:21:11
P线程库不直接支持此操作。
作为解决办法,您可以定义一个互斥锁来保护锁:
这样,当您试图升级写锁时,没有其他线程可以抓取它。但是,当您试图升级时,如果其他线程持有读锁,则您的线程将阻塞。
此外,如前所述,如果两个线程同时试图升级同一锁,则会遇到死锁:
阻止。
从我的CS讲座中吸取教训:死锁是无法可靠地避免的。对于提出的每个策略,至少有一个用例表明该策略是不切实际的。您唯一能做的就是检测死锁条件(即,如果调用在EDEADLK中失败),并确保您的代码已经准备好处理这种情况。(如何恢复在很大程度上取决于代码。)
以这种方式降级并不容易出现死锁,尽管降级和同时升级会导致死锁。如果只有一个线程以这种方式升级了该锁(如果需要,其他线程会立即获得写锁),也不会出现死锁。
正如其他人所说,当您可能需要时立即获得写锁,这将是一种不容易发生死锁的替代方法,但可能不必要地阻止其他读取操作同时进行。
结论:这取决于您的代码.
如果只读阶段很短(即足够短,以便您能够在那段时间内阻止其他读取操作),那么我将采用无偿的写锁方法。
如果只读阶段可能会持续很长时间,并且在此期间阻塞其他读取是不可接受的,那么进行互斥保护的锁升级,但是要么将其限制为每个锁一个线程(“只有T1可以升级锁L42,而不是其他线程”),或者提供一种检测死锁并从死锁中恢复的方法。
除非除此锁及其互斥项以外的其他资源发挥作用
发布于 2010-03-09 08:46:54
最简单和最安全的方法是从您想要更改数据的那一刻起就使用写锁,而不是从您确定要更改数据的那一刻开始。我知道这将使对数据的访问更加序列化。
当我读到这个问题时,我有点惊讶,因为我从来没有考虑过先读锁,然后升级到写锁。不同的情况可能需要不同的方法。
https://stackoverflow.com/questions/2407558
复制相似问题