多线程编程中经常用锁来控制对全局变量的访问。多线程编程中必须确保多个线程不会同时修改同一变量,或者某一线程不会读取正在由其他线程修改的变量。下面是一个例子:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
 
int sum = 0;
 
void* adder(void *p)
{
    for(int i = 0; i < 100000; i++)  // 十万
    {
        sum++;
    }
 
    return NULL;
}
 
int main()
{
    pthread_t threads[10];
 
    for(int i = 0; i < 10; i++)
    {
        pthread_create(&threads[i], NULL, adder, NULL);
    }
    
    for(int i = 0; i < 10; i++)
    {
        pthread_join(threads[i],NULL);
    }
 
    printf("sum is %d\n", sum);
}

程序输出结果小于1000000,这是由于对sum不能确保为原子操作,因此必须需要锁来实现线程同步。

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
 
int sum = 0;
pthread_mutex_t mutex;
 
void* adder(void *p)
{
    for(int i = 0; i < 1000000; i++)  // 百万次
    {
        pthread_mutex_lock(&mutex);
      sum++;
      pthread_mutex_unlock(&mutex);
    }
 
    return NULL;
}
 
int main()
{
    pthread_t threads[10];
    pthread_mutex_init(&mutex, NULL);
 
    for(int i = 0; i < 10; i++)
    {
        pthread_create(&threads[i], NULL, adder, NULL);
    }
    
    for(int i = 0; i < 10; i++)
    {
        pthread_join(threads[i],NULL);
    }
 
    printf("sum is %d\n", sum);
}

上面的程序通过互斥量,可以确保每次执行结果均为正常。当然实现线程同步的方法不止这一种,最近在编译32位项目代码时接触到gcc4.1.2版本后内置的原子操作,就是传说中的无锁锁。首先gcc官网介绍性能有所提升,一个比较简单的例子,如果想要在gcc版本低于4.1.2的版本上使用这种机制应该如何实现呢?

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
 
static int count = 0;
 
void *test_func(void *arg)
{
    int i=0;
    for(i=0; i < 20000; i++) {
        __sync_fetch_and_add(&count,1);
        //count++;
    }
    return NULL;
}
 
int main(int argc, const char *argv[])
{
    pthread_t id[20];
    int i = 0;
 
    for(i=0; i < 20; i++) {
        pthread_create(&id[i],NULL,test_func,NULL);
    }
 
    for(i=0; i<20; ++i) {
        pthread_join(id[i],NULL);
    }
 
    printf("%d\n",count);
    return 0;
}