大多数__sync_local_test_and_set的搜索结果都提到它可以用来实现自旋锁而不是互斥锁。文章多线程编程:锁定效率还读到:I could not think of a means to implement mutex without closely interacting with the kernel(futex system call),并给出了一个用__sync_lock_test_and_set实现自旋锁的示例。
但是我认为__sync_lock_test_and_set也可以用来实现互斥锁:
if (__sync_lock_test_and_test(&lock, 1) == 0) {
// we get the lock, do our work
lock = 0; // or __sync_lock_release(&lock);
} else {
// the lock has already been token.
}这是互斥锁吗?
提前感谢!
发布于 2022-10-14 13:54:02
首先,Linux是特定于__sync_*内核的。在其他上下文中,您可能希望使用来自<stdatomic.h>的<stdatomic.h>原子类型和函数(或来自<atomic>的C++11 std::atomic )。
你的算法就其本身而言是可行的。但问题是,// the lock has already been taken的内容是什么。你在那个街区做什么?在大多数情况下,你必须做的“工作”不是可选的。您不能直接跳过它;您必须等待并在锁可用时立即执行它。本质上,您编写的只是典型互斥体的trylock和unlock函数。难度更大的是lock。
你想:
你可以通过做这样的事情来完成#1
while (atomic_flag_test_and_set(&lock, 1) == 1) {
thrd_yield();
// or: thrd_sleep(short_time);
}但是仍然会有等待线程频繁地醒来,只会测试互斥锁,发现它仍然不可用,然后继续睡觉。这可能不会占用太多的CPU时间,但它确实强制了许多不必要的上下文切换,这是不免费的。
这在#2上做得不太好,因为当互斥锁可用时,这个线程将不会立即唤醒它;它将不得不等待直到它碰巧得到另一个时间片(在thrd_yield()的情况下)或直到它的short_time过期。这不必要地减缓了你的程序。
而且它根本没有完成第三项任务。如果有几个线程在同一个互斥体上等待,它基本上是随机的,一个线程最终会占用它,而一些线程可能会比其他线程等待的时间长得多。
因此,您确实需要操作系统的支持才能正确地执行lock。操作系统可以在这个特定的互斥对象上创建一个等待线程的队列,并让它们在不可用的情况下保持休眠状态。当另一个线程解锁互斥锁时,操作系统可以选择队列中最老的线程(或应用其他一些聪明的基于优先级的算法),唤醒该线程,并且只唤醒该线程,并确保它在唤醒时确实持有互斥锁。
没有操作系统支持,除了spinlock或它的一些稍微美化的变体之外,您什么也做不了。
https://stackoverflow.com/questions/74069004
复制相似问题