haisql_memcache兼容性与并发性
一.独特的“spin_lock”结构
原本的锁,当在单线程cpu下使用时,会不兼容不能使用,只能在双核的cpu下执行,这样就给许多用户带来不便。而我们自己设计的独特的“spin_lock”,在程序中加上了“yield()”这个用法,同时使用了“读栅栏”和“写栅栏”的功能,不仅使程序在关键语句上不会乱序执行,同时还兼容了在单核cpu下的执行操作功能,使其在单核cpu和多核cpu下都能执行,代码不仅简洁,同时性能也远远优于一般使用的锁。
以下是我公司设计的一个高性能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产生任何影响, 只要锁不释放, 永远不会内存总线的争夺, 因此大大提高了整体的效率。
二.适合“session”缓存服务软件使用
使用session增加了服务器的安全性,减少了安全隐患,session 允许通过将对象存储在 Web服务器的内存中在整个用户会话过程中保持任何对象,因为浏览器不需要存储任何这种信息,所以可以使用任何浏览器。使用本内存数据库软件作为www服务器的“session”缓存服务软件使用,提供了极高的性能和极大的并发性。