多线程编程中经常用锁来控制对全局变量的访问。多线程编程中必须确保多个线程不会同时修改同一变量,或者某一线程不会读取正在由其他线程修改的变量。下面是一个例子:
#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.0(含)版本后内置的原子操作,就是传说中的无锁锁。首先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;
}