我在8个线程(我是一个8核PC)之间有一个共享哈希表,每个线程都在哈希表中读写。
在示例1中,我使用了经典的互斥锁,所有8个核心都是100% 在示例2中,我使用了shared_timed_mutex,因为读访问可以在竞争中,但所有8核都在40%
问题出在哪里?
example 1:
mutex mutex_hash;
-- thread --
mutex_hash.lock();
//read
mutex_hash.unlock();
..
mutex_hash.lock();
//write
mutex_hash.unlock();
============================
example 2:
shared_timed_mutex mutex_hash;
-- thread --
mutex_hash.lock_shared();
//read
mutex_hash.unlock_shared();
..
mutex_hash.lock();
//write
mutex_hash.unlock();
答案 0 :(得分:6)
由于你的问题有些含糊不清,除了你自己以外的任何人都无法重现这种行为,我只能猜测。
我最好的猜测是:
shared_timed_mutex
并不总是比mutex
好。如果是,则不需要mutex
。我们只需要摆脱mutex
,将shared_timed_mutex
重命名为mutex
,然后过上幸福的生活。不幸的是,现实生活比这复杂得多。
有时mutex
是优秀的工具。有时shared_timed_mutex
是优秀的工具。
例如:如果我们有8个线程争用互斥锁,并且每个线程有50%的概率需要读取或写入,并且读取和写入任务需要保持互斥量大约相同的时间量,那么那里使用shared_timed_mutex
类型收效甚微。
要理解这一点,请考虑同时请求shared_timed_mutex
的所有8个线程的场景。如果作者首先得到它(概率为50%),则所有其他7个线程都会阻塞(就像我们使用mutex
一样)。
在另外50%的时间里,读者首先得到它。请求锁定的第二个线程有50/50的机会成为读者。如果是作家,公平的实施将阻止其余的读者获得锁定。这发生在0.5 * 0.5 == 25%的时间。所以现在我们高达75%的时间,一次只能运行一个线程:{W,阻止...}和{R,W,阻止......}。
25%的时间我们得到{R,R,?...},其中至少有两个线程可以同时运行。
嗯,至少25%没有两个,也许更多线程一次运行值得吗?
取决于。
mutex
比shared_timed_mutex
简单。更简单的代码可以实现更快的代码。
shared_timed_mutex
会发光。
例如,如果您的数据库保持不可变,除了每年更新6次(并且需要1秒更新),读取该数据库并锁定共享shared_timed_mutex
是很有意义的模式。人们可以轻松地以独特模式每两个月锁定一次。
但是,如果您每秒都尝试更新该数据库,这是完全不同的情况,shared_timed_mutex
可能根本不会为您提供任何性能优势。在这种情况下,要求每个人(读者和作者)要求独占访问(因为逻辑更简单)可能更便宜。