如何实现一个比互斥锁快100倍并且消耗最少CPU的通用“锁”(2)

一个现实中使用C++实现的多线程同步锁:

class PosixLock{
public:
    explicit PosixLock(){
        pthread_mutexattr_t attr;
        pthread_mutexattr_init(&attr);
        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
        pthread_mutex_init(&_mutex, &attr);
    }

    void Lock(){
        pthread_mutex_lock(&_mutex);
    }

    void Unlock(){
        pthread_mutex_unlock(&_mutex);
    }

    ~PosixLock(){
        pthread_mutex_destroy(&_mutex);
    };

private:
    pthread_mutex_t _mutex;
};

typedef PosixLock PoolLock;

class  LockScoped {
public:
    explicit LockScoped(PoolLock* lock): _lock(lock) {
        _lock->Lock();
    }

    explicit LockScoped(std::shared_ptr sharelock): _lock(sharelock.get()) {
        _lock->Lock();
    }

    ~LockScoped(){
        _lock->Unlock();
    }

    //To prevent alloc LockScoped in heap memory,
    //Only alloc LockScoped in stack memory
    void* operator new (std::size_t size) throw (std::bad_alloc) = delete;
    void* operator new[] (std::size_t size) throw (std::bad_alloc) = delete;
    void operator delete (void *) = delete;
    void operator delete[] (void *) = delete;

private:
    PoolLock* _lock;
};

使用LockScoped做线程间同步:

mempool::PoolLock lock;
void *threadSyncwork(void *argument){
    for (int64_t i = 0; i < addPerforTimes; i++) {
        mempool::LockScoped ls(&lock);
        globalCount++;
    }
    return NULL;
}

然后使用互斥体pthread_mutex_t是有代价的,具体代价多大,我们做一个简单的性能测试:
使用LockScoped和完全不考虑同步执行一亿(100000000)次比较:

这里写图片描述

上图测试结果是在Mac Pro: 3.1 GHz Intel Core i7 , 16 GB 1867 MHz DDR3 机器上的一次测试结果,

绝对值没有意义,关键是相对值,可以看到效率相差10万倍量级。

事实上上面的相对值测试结果也是没有什么意义的,因为不考虑同步情况下,测试时间基本是不随循环次数增长的常量。

但这个测试告诉我们一个事实,使用互斥锁的有代价的,而且这个代价在有些情况下是巨大的,大到有些情况下会成为系统瓶颈。

完整测试代码如下:

//
//  threadPosixLockPerfTest.cpp
//  mempool
//
//  Created by gjwang on 10/24/15.
//  Copyright (c) 2015 gjwang. All rights reserved.
//

#include 
#include 
#include 
#include 
#include 

#include "threadPosixLockPerfTest.h"
#include "PoolLock.h"

#ifndef _INT64_T
#define _INT64_T
typedef long long int64_t;
#endif

#define NUM_THREADS (2)

static int64_t  globalCount = 0;
static const int64_t  addPerforTimes = 100000000;
static const int testTimes = 10;

void *threadNonSyncwork(void *argument){
    for (int64_t i = 0; i < addPerforTimes; i++) {
        globalCount++;
    }
    return NULL;
}

mempool::PoolLock lock;
void *threadSyncwork(void *argument){
    for (int64_t i = 0; i < addPerforTimes; i++) {
        mempool::LockScoped ls(&lock);
        globalCount++;
    }
    return NULL;
}

void threadLockPerfTest(void *(*threadWorkerFunc)(void *)){
    pthread_t threads[NUM_THREADS];
    struct timeval timeBegin;
    struct timeval timeEnd;
    globalCount = 0;
    int index;
    gettimeofday(&timeBegin, NULL);
    for (index = 0; index < NUM_THREADS; ++index) {
        pthread_create(&threads[index], NULL, threadWorkerFunc, NULL);
    }

    for (index = 0; index < NUM_THREADS; ++index) {
        pthread_join(threads[index], NULL);
    }
    gettimeofday(&timeEnd, NULL);

    std::cout << std::setw(8) <<
    (timeEnd.tv_sec - timeBegin.tv_sec)*1000000 +
    (timeEnd.tv_usec-timeBegin.tv_usec) << " ";
}


int main(int argc, const char * argv[]) {
    int i;
    std::cout << "thread Non sync Performance: usec" << std::endl;

    for (i = 0; istd::cout << std::endl;
    std::cout << "thread Posix sync Performance: usec" << std::endl;

    for (i = 0; istd::cout << std::endl;
}

编译命令:

g++ -std=gnu++11 -O0 threadPosixLockPerfTest.cpp PoolLock.cpp -o threadPosixLockPerfTest && ./threadPosixLockPerfTest

github 代码:

https://github.com/gjwang/mempool/blob/master/mempool/threadPosixLockPerfTest.cpp

https://github.com/gjwang/mempool/blob/master/mempool/threadPosixLockPerfTest.h

https://github.com/gjwang/mempool/blob/master/mempool/PoolLock.h

你可能感兴趣的:(c++,多线程,免锁设计)