代码
代码如下
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