上篇文章《c语言数据结构实现-数组队列/环形队列》讲述了数组队列的原理与实现,本文编写一个双线程进行速度测试
多线程编程接口:
1) 创建线程 pthread_create 函数
SYNOPSIS
#include
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Compile and link with -pthread.
DESCRIPTION:
The pthread_create() function starts a new thread in the calling process. The new thread starts execution by invoking start_routine(); arg is passed as the sole argument of start_routine().
RETURN VALUE:
On success, pthread_create() returns 0; on error, it returns an error number, and the contents of *thread are undefined.
2) 设置线程属性 pthread_attr_setdetachstate
SYNOPSIS
#include
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
Compile and link with -pthread.
DESCRIPTION
The pthread_attr_setdetachstate() function sets the detach state attribute of the thread attributes object referred to by attr to the value specified in detachstate. The detach state attribute determines whether a thread created using the thread attributes object attr will be created in a joinable or a detached state.
RETURN VALUE
On success, these functions return 0; on error, they return a nonzero error number.
3) 线程锁 pthread_mutex_init、pthread_mutex_lock、pthread_mutex_unlock、pthread_mutex_destory
线程锁是用于多线程直接的同步,用来保护临界资源(数值队列),同样类似的功能有 Posix 的 sem信号量。
4) 条件变量 pthread_cond_init、pthread_cond_signal、pthread_cond_wait、pthread_cond_destroy
条件变量是同步线程的一种机制,它允许线程挂起,让出处理器等待其他线程向它发送信号,该线程收到该信号后被唤醒继续执行程序。
数据结构 test_t 为用户数据,instance_t 为程序上下文
typedef struct item_t
{
int value;
} test_t;
typedef struct instance
{
sem_t sem_mutex;
pthread_mutex_t thd_mutex;
pthread_cond_t thd_cond;
bufqueue_t queue;
} instance_t;
主线程创建子线程,并生产数据进行入列操作,顺序地生产 times 个 pitem 数据进行入列,生产完成后等待子线程消费
线程的工作方式分别有三种:线程完全异步的机制、使用sem保证实时线程同步、使用条件变量保持同步
int test_mutilthread(int times)
{
int ret = FAILURE;
int ix = 0;
pthread_t tid = 0;
pthread_attr_t attr;
instance_t inst = {.queue = {0}};
test_t *pitem = NULL;
#ifdef TEST_SEM
printf("Sem sem_mutex mode\n");
assert(SUCCESS == ( ret = sem_init(&inst.sem_mutex, 0, 0) ));
#elif defined(TEST_COND)
printf("Pthread Cond mode\n");
assert(SUCCESS == ( ret = pthread_mutex_init(&inst.thd_mutex, NULL) ));
assert(SUCCESS == ( ret = pthread_cond_init(&inst.thd_cond, NULL) ));
#endif
assert(SUCCESS == ( ret = bufqueue_create(&inst.queue, times, sizeof(test_t)) ));
assert(SUCCESS == ( ret = pthread_attr_init(&attr) ));
assert(SUCCESS == ( ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) ));
assert(SUCCESS == ( ret = pthread_create(&tid, NULL, __do_customer, &inst) ));
/* Producer */
for ( ix = 1; ix < times; ix++ ) {
assert(NULL != ( pitem = (test_t*)bufqueue_tail(&inst.queue) ));
/* Set custom item */
pitem->value = ix;
assert(SUCCESS == ( ret = bufqueue_push(&inst.queue) ));
printf("Enqueue %u/%u\n", pitem->value, ix);
#ifdef TEST_SEM
sem_post(&inst.sem_mutex);
#elif defined(TEST_COND)
pthread_cond_signal(&inst.thd_cond);
#endif
}
while ( !bufqueue_isempty(&inst.queue) ) {
printf("Wait dequeue...\n");
usleep(300);
}
ret = SUCCESS;
_E1:
pthread_attr_destroy(&attr);
bufqueue_destroy(&inst.queue, free);
#ifdef TEST_SEM
sem_destroy(&inst.sem_mutex);
#elif defined(TEST_COND)
pthread_cond_destroy(&inst.thd_cond);
pthread_mutex_destroy(&inst.thd_mutex);
#endif
return ret;
}
线程的工作方式分别也有三种:线程完全异步的机制、使用sem保证实时线程同步、使用条件变量保持同步
static void *__do_customer(void *args)
{
instance_t *pinst = (instance_t *)args;
test_t *pitem = NULL;
u32 cnt = 1;
u32 max = 0;
ASSERT_FAIL(NULL, args);
for ( max = pinst->queue.size; cnt < max; ) {
#ifdef TEST_SEM
sem_wait(&pinst->sem_mutex);
#elif defined(TEST_COND)
if ( bufqueue_isempty(&pinst->queue) ) {
pthread_mutex_lock(&pinst->thd_mutex);
pthread_cond_wait(&pinst->thd_cond, &pinst->thd_mutex);
pthread_mutex_unlock(&pinst->thd_mutex);
printf("Wait enqueue...\n");
continue;
}
#else
if ( bufqueue_isempty(&pinst->queue) ) {
usleep(300);
printf("Wait enqueue...\n");
continue;
}
#endif
assert(NULL != (pitem = (test_t*)bufqueue_pop(&pinst->queue) ));
assert(cnt++ == pitem->value);
printf("Dequeue %u/%u\n", pitem->value, cnt);
}
printf("Dequeue Done\n");
_E1:
return NULL;
}
int main(int argc, char *argv[])
{
int ret = FAILURE;
u32 times = 1024;
if ( argc > 1 ) {
times = atoi(argv[1]);
}
ret = test_mutilthread(times)
printf("Test result:\t\t\t\t[%s]\n", ret ? "FAILURE" : "SUCCESS");
exit(ret ? 1 : 0);
}
注意以上写法为原型断言的写法,保证断言失败时程序立刻退出,仅为测试使用,不符合实际的代码规范
测试硬件为Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz
样本大小:100'000个
主线程得知队列空的情况后,加入一个时间统计的功能,分别得出一秒钟操作的速度:
参考文章:
[1] Linux C++的多线程编程, http://www.cnblogs.com/youtherhome/archive/2013/03/17/2964195.html
[2] 多线程编程-互斥锁 http://blog.chinaunix.net/uid-21411227-id-1826888.html