2014年01月25日 星期六 10:21
atomic模块提供了对于32位整数以及指针的原子操作方法。
在并发运行的环境下,对于共享数据的读写操作,如果不采取任何保护措施,那么操作结果有很大可能是错误的。我们可以使用mutex进行加锁,但这样做会严重影响程序的运行效率。atomic模块提供的原子操作可以让我们放心大胆的在不加锁的情况下对共享数据进行读写操作。
如下示例程序演示了三种操作共享数据的方式:不采取任何措施,加锁,使用atomic。
三种方式运行对比结果如下:
1,不采取任何措施,操作结果错误,运行速度最快。
2,加锁,操作结果正确,但运行速度最慢。
3,使用atomic原子操作,操作结果正确,运行速度居中。
#include <stdio.h>
#include <apr.h>
#include <apr_pools.h>
#include <apr_errno.h>
#include <apr_strings.h>
#include <apr_thread_pool.h>
#include <apr_atomic.h>
apr_uint32_t var=0;
void apr_err(const char *s, apr_status_t rv)
{
    char buf[120];
    fprintf(stderr, "%s: %s (%d)\n", s, 
            apr_strerror(rv, buf, sizeof buf), rv);
}
void *thread_func_normal(apr_thread_t *thd,void *arg) {
    for(int j=0;j<10000000;j++) {
        var++;
    }
    return NULL;
}
void *thread_func_atomic(apr_thread_t *thd,void *arg) {
    for(int j=0;j<10000000;j++) {
        apr_atomic_inc32(&var);
    }
    return NULL;
}
apr_thread_mutex_t *mutex;
void *thread_func_mutex(apr_thread_t *thd,void *arg) {
    for(int j=0;j<10000000;j++) {
        apr_thread_mutex_lock(mutex);
        var++;
        apr_thread_mutex_unlock(mutex);
    }
    return NULL;
}
int main(int argc,char **argv) {
    apr_initialize();
    apr_pool_t *pool;
    apr_pool_create(&pool,NULL);
    apr_status_t st;
    char *method;
    if(argc > 1) {
        method=argv[1];
    } else {
        method="normal";
    }
    printf("method: %s\n",method);
    
    apr_atomic_init(pool);
    apr_thread_mutex_create(&mutex,APR_THREAD_MUTEX_DEFAULT,pool);
    
    apr_thread_pool_t *tpl;
    st=apr_thread_pool_create(&tpl,8,128,pool);
    apr_size_t n;
    
    for(long i=0;i<30;i++) { 
        if(strcmp(method,"mutex") == 0) {
            apr_thread_pool_push(tpl,thread_func_mutex, (void *)i,
                    APR_THREAD_TASK_PRIORITY_NORMAL,NULL);
        } else if(strcmp(method,"atomic") == 0) {
            apr_thread_pool_push(tpl,thread_func_atomic,(void *)i,
                    APR_THREAD_TASK_PRIORITY_NORMAL,NULL);
        } else {
            apr_thread_pool_push(tpl,thread_func_normal,(void *)i,
                    APR_THREAD_TASK_PRIORITY_NORMAL,NULL);
        }
    }
    for(long i=0;i<20;i++) {
        n=apr_thread_pool_busy_count(tpl);
        printf("busy thread : %d\n",n);
        apr_sleep(1000000);
        if(n == 0) {
            break;
        }
        printf("var = %u\n",var);
    }
    printf("finally, var = %u\n",var);
        
    apr_thread_pool_destroy(tpl);
    apr_pool_destroy(pool);
    apr_terminate();
    return 0;
}
参考资料:
Zeuux © 2025
京ICP备05028076号