- 论坛徽章:
- 9
|
下面是我设计的一个高性能spin_lock, 可以挑战目前所有linux下的spin_lock版本。
class Spin_lock
{
public:
Spin_lock( void );
void lock( void );
bool try_lock( void );
void unlock( void );
Spin_lock( const Spin_lock& ) = delete;
Spin_lock& operator = ( const Spin_lock& ) = delete;
private:
std::atomic<bool> d_atomic_bool;
};
Spin_lock::Spin_lock()
{
d_atomic_bool.store( false, std::memory_order_relaxed );
return;
}
void Spin_lock::lock( void )
{
while( d_atomic_bool.exchange( true, std::memory_order_acquire ) ) {
while( 1 ) {
_mm_pause(); // pause指令 延迟时间大约是12纳秒
if( !d_atomic_bool.load( std::memory_order_relaxed ) ) break;
std::this_thread::yield(); // 在无其他线程等待执行的情况下,延迟时间113纳秒
// 在有其他线程等待执行情况下,将切换线程
if( !d_atomic_bool.load( std::memory_order_relaxed ) ) break;
continue;
}
continue;
}
return;
}
bool Spin_lock::try_lock( void )
{
return !d_atomic_bool.exchange( true, std::memory_order_acquire );
}
void Spin_lock::unlock( void )
{
d_atomic_bool.store( false, std::memory_order_release ); // 设置为false
return;
}
我们的核心lock()代码中关键的第1行
while( d_atomic_bool.exchange( true, std::memory_order_acquire ) )
首先是使用了更高效率的exchange, 要比CAS指令有更高的效率,是内存读写模式,每次都要独占cache,并且将其他CPU的cache设置为invalide, 如果只有这1行代码,那么 如果两个以上CPU在等待这把锁,将交替将64字节Cacheline内存反复同步, 数据冲突激烈,影响其他线程的内存操作,降低整体性能, 影响全部CPU的工作效率, 因为产生了内存争用, 产生了总线争用
因此我们提供了第2行关键检测代码:
if( !d_atomic_flag.load( std::memory_order_relaxed ) ) break
该指令主要是为了减少CAS指令循环对内存总线带来的不良影响, 这个循环只有在锁被释放后, 才会跳出循环, 但是这个指令消耗的资源极少。这组指令是 只读模式检查, 只需要锁没有被释放, 这里继续循环, 但是这组spin是没有竞争状态的, 不会对内存和cache产生任何影响, 只要锁不释放, 永远不会内存总线的争夺, 因此大大提高了整体的效率 |
|