在 C++ 中使用原子 TestAndSet 混合无锁和全锁线程同步
Mixing lock-less and lock-full thread synchronization with atomic TestAndSet in C++
我有一个消费者线程,它必须从缓冲区读取 而不锁定 。如果因为生产者线程正在写入缓冲区而必须跳过该操作,那也没关系。因此,在我看来,最合适的选择是在某些标志上使用 atomic TestAndSet。
现在,前面提到的那些生产者线程也必须遵守此标志,因为它们无法在消费者正在读取缓冲区时开始写入缓冲区。我可以像下面的代码一样使用 atomic_flag::test_and_set 来解决这个问题:
while (flag.test_and_set())
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
...但是编写我自己的自旋锁似乎不太理想。我宁愿让我的线程休眠,直到它因清除标志而被唤醒。类似于:
flag.enter();
TLDR:如何最好地同步两个线程,其中一个可以锁定而另一个不能?
您不能混合搭配同步方法 - 双方必须同意。在我看来,您真正想要的是尝试获取锁,然后如果失败,则跳过。您可以在常规 std::mutex
上使用 try_lock 来实现此目的。
如果您希望生产者在 reader 正在读取时阻塞,则无锁是不可能的。
使用 std::mutex
.
读者可以使用try_lock
避免阻塞
作者(制作人)可以照常使用屏蔽lock
功能
当然,为了避免锁泄漏,请使用std::unique_lock
. Readers should pass std::try_to_lock
as the second argument. You should then check owns_lock()
查看数据是否可以安全读取或是否正在进行写入。
我有一个消费者线程,它必须从缓冲区读取 而不锁定 。如果因为生产者线程正在写入缓冲区而必须跳过该操作,那也没关系。因此,在我看来,最合适的选择是在某些标志上使用 atomic TestAndSet。
现在,前面提到的那些生产者线程也必须遵守此标志,因为它们无法在消费者正在读取缓冲区时开始写入缓冲区。我可以像下面的代码一样使用 atomic_flag::test_and_set 来解决这个问题:
while (flag.test_and_set())
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
...但是编写我自己的自旋锁似乎不太理想。我宁愿让我的线程休眠,直到它因清除标志而被唤醒。类似于:
flag.enter();
TLDR:如何最好地同步两个线程,其中一个可以锁定而另一个不能?
您不能混合搭配同步方法 - 双方必须同意。在我看来,您真正想要的是尝试获取锁,然后如果失败,则跳过。您可以在常规 std::mutex
上使用 try_lock 来实现此目的。
如果您希望生产者在 reader 正在读取时阻塞,则无锁是不可能的。
使用 std::mutex
.
读者可以使用try_lock
避免阻塞
作者(制作人)可以照常使用屏蔽lock
功能
当然,为了避免锁泄漏,请使用std::unique_lock
. Readers should pass std::try_to_lock
as the second argument. You should then check owns_lock()
查看数据是否可以安全读取或是否正在进行写入。