性能对比pthread mutex/spin lock/spin lock delay

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sun_ashe/article/details/81636756

代码

代码如下
main.cc

//
// Created by sun_ashe on 2018/8/13.
//

#include <iostream>
#include <pthread.h>
#include "spin.h"

using std::cout;
using std::endl;

pthread_mutex_t m1;
unsigned  int delay;

void* auto_increment_mutex(void *arg)
{
    unsigned long int max=*(unsigned long int*)arg;
    unsigned long  int i =0;
    pthread_mutex_init(&m1,NULL);
    while(i<max)
    {
        if(pthread_mutex_lock(&m1) ==0 )
        {
            //cout<< "add lock" << pthread_self() <<endl;
            i++;
        }

        pthread_mutex_unlock(&m1);
        sched_yield();
    }

    cout << i << endl;
}


void* auto_increment_spin_lock(void* arg)
{
    unsigned long int max=*(unsigned long int*)arg;
    unsigned long int i=0;

    while(i<max)
    {
        while(!tas_lock())
        {
            //ut_delay(delay);
        }

        i++;

        tas_unlock();
    }

    cout << i <<endl;
}


void* auto_increment_spin_lock_delay(void* arg)
{
    unsigned long int max=*(unsigned long int*)arg;
    unsigned long int i=0;

    while(i<max)
    {
        while(!tas_lock())
        {
            ut_delay(delay);
        }

        i++;

        tas_unlock();
    }

    cout << i <<endl;
}



int main(int argc,char* argv[])
{
    int thread_num=atoi(argv[1]);
    unsigned long int max=atol(argv[2]);
    const int lock_type = atoi(argv[3]);
    delay = atoi(argv[4]);

    pthread_mutex_init(&m1,NULL);
    pthread_mutex_lock(&m1);
    pthread_mutex_unlock(&m1);
    pthread_t p[thread_num];
    for(int i=0;i<thread_num;i++)
    {
        if(lock_type == 0)
        {
            pthread_create(&p[i], NULL, auto_increment_mutex, (void *) &max);
        }
        else if(lock_type == 1)
        {
            pthread_create(&p[i],NULL,auto_increment_spin_lock,(void*) &max);
        }
        else if(lock_type == 2)
        {
            pthread_create(&p[i],NULL,auto_increment_spin_lock_delay,(void*) &max);
        }

    }

    for(int i=0;i<thread_num;i++)
    {
        pthread_join(p[i],NULL);
    }

    return 0;
}

spin.h

//
// Created by sun_ashe on 2018/8/13.
//

#ifndef TEST_SPIN_H
#define TEST_SPIN_H
extern unsigned long int MUTEX_STATE_LOCKED;
extern unsigned long int MUTEX_STATE_UNLOCKED;

extern unsigned long int  m_lock_word;

extern unsigned long int
os_atomic_test_and_set(
        volatile unsigned long int*   ptr,
        unsigned long int    new_val);




#define TAS(l, n)           os_atomic_test_and_set((l), (n))

bool tas_lock();
bool tas_unlock();


#  ifdef __SUNPRO_CC
#   define UT_RELAX_CPU() asm ("pause" )
#  else
#   define UT_RELAX_CPU() __asm__ __volatile__ ("pause")
#  endif /* __SUNPRO_CC */

# if defined(HAVE_HMT_PRIORITY_INSTRUCTION)
#  define UT_LOW_PRIORITY_CPU() __asm__ __volatile__ ("or 1,1,1")
  #  define UT_RESUME_PRIORITY_CPU() __asm__ __volatile__ ("or 2,2,2")
# else
#  define UT_LOW_PRIORITY_CPU() ((void)0)
#  define UT_RESUME_PRIORITY_CPU() ((void)0)
# endif


extern unsigned long int ut_delay(
        /*=====*/
        unsigned long int delay);  /*!< in: delay in microseconds on 100 MHz Pentium */


#endif

spin.cc

//
// Created by sun_ashe on 2018/8/13.
//

#include "spin.h"

unsigned long int MUTEX_STATE_LOCKED = 1;
unsigned long int MUTEX_STATE_UNLOCKED = 0;

unsigned long int  m_lock_word = 0;

bool tas_lock()
{
    return(TAS(&m_lock_word, MUTEX_STATE_LOCKED) == MUTEX_STATE_UNLOCKED);
}

bool tas_unlock()
{
    TAS(&m_lock_word, MUTEX_STATE_UNLOCKED);
}

unsigned long int ut_delay(
        /*=====*/
        unsigned long int delay)  /*!< in: delay in microseconds on 100 MHz Pentium */
{
    unsigned long int i, j;

    UT_LOW_PRIORITY_CPU();

    j = 0;

    for (i = 0; i < delay * 50; i++) {
        j += i;
        UT_RELAX_CPU();
    }

    UT_RESUME_PRIORITY_CPU();

    return j;
}


extern unsigned long int
os_atomic_test_and_set(
        volatile unsigned long int*   ptr,
        unsigned long int    new_val)
{
    unsigned long int ret;
    /* Silence a compiler warning about unused ptr. */
    (void) ptr;
#if defined(__powerpc__) || defined(__aarch64__)
    __atomic_exchange(ptr, &new_val,  &ret, __ATOMIC_SEQ_CST);
#else
    __atomic_exchange(ptr, &new_val,  &ret, __ATOMIC_RELEASE);
#endif
    return(ret);
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.9)
project(test)

set(CMAKE_CXX_STANDARD 11)


add_executable(spin_lock main.cc spin.cc)
target_link_libraries(spin_lock pthread)

项目可以直接cmake,make,下面看测试结果。

测试

测试对比8线程下,每个线上加锁顺序操作,然后分别递增10000000的时间消耗

mutex

ashe@macos ~/Desktop/github/test/spin_lock $ time ./spin_lock 8 10000000 0 10
10000000
10000000
10000000
10000000
10000000
10000000
10000000
10000000

real    5m41.077s
user    2m13.860s
sys     5m58.657s

spin lock

ashe@macos ~/Desktop/github/test/spin_lock $ time ./spin_lock 8 10000000 1 10
10000000
10000000
10000000
10000000
10000000
10000000
10000000
10000000

real    0m25.075s
user    3m5.460s
sys     0m0.465s

spin lock delay

ashe@macos ~/Desktop/github/test/spin_lock $ time ./spin_lock 8 10000000 2 10
10000000
10000000
10000000
10000000
10000000
10000000
10000000
10000000

real    0m1.496s
user    0m11.421s
sys     0m0.023s

猜你喜欢

转载自blog.csdn.net/sun_ashe/article/details/81636756