Mat*_*att 53 multithreading operating-system mutex pthreads atomic
对于像计数器那样简单的东西,如果多个线程将增加数量.我读到互斥锁会降低效率,因为线程必须等待.所以,对我来说,一个原子计数器将是最有效的,但我在内部读到它基本上是一个锁?所以我想我很困惑如何比另一个更有效率.
Cor*_*ica 29
如果您有一个支持原子操作的计数器,它将比互斥锁更有效.
从技术上讲,原子将在大多数平台上锁定内存总线.但是,有两个改善的细节:
yah*_*ahe 27
原子操作利用处理器支持(比较和交换指令)并且根本不使用锁,而锁更依赖于操作系统,并且在例如Win和Linux上执行不同.
锁实际上暂停了线程执行,为其他任务释放了cpu资源,但在停止/重新启动线程时会产生明显的上下文切换开销.相反,尝试原子操作的线程不会等待并继续尝试直到成功(所谓的忙等待),因此它们不会产生上下文切换开销,但也不会释放cpu资源.
总而言之,如果线程之间的争用足够低,通常原子操作会更快.你肯定应该做基准测试,因为没有其他可靠的方法可以知道上下文切换和忙等待之间的最低开销.
LWi*_*sey 11
最低(符合标准)互斥实现需要2个基本要素:
由于C++标准要求的"同步"关系,你无法使它变得更简单.
最小(正确)实现可能如下所示:
class mutex {
std::atomic<bool> flag{false};
public:
void lock()
{
while (flag.exchange(true, std::memory_order_relaxed));
std::atomic_thread_fence(std::memory_order_acquire);
}
void unlock()
{
std::atomic_thread_fence(std::memory_order_release);
flag.store(false, std::memory_order_relaxed);
}
};
Run Code Online (Sandbox Code Playgroud)
由于它的简单性(它不能暂停执行的线程),很可能在低争用下,这个实现优于a std::mutex.但即便如此,很容易看到受此互斥锁保护的每个整数增量都需要以下操作:
atomic商店释放互斥锁atomic比较并交换(读-修改-写)来获取该互斥(可能多次)如果将其与std::atomic<int>使用单个(无条件)读取 - 修改 - 写入(例如fetch_add)递增的独立项进行比较,则可以合理地预期原子操作(使用相同的排序模型)将优于以下情况:互斥体是用过的.
原子整数是一个用户模式对象,因为它比在内核模式下运行的互斥锁效率更高。原子整数的范围是单个应用程序,而互斥锁的范围是计算机上所有正在运行的软件的范围。