实现线程同步
1 为何需要线程同步?
由于线程共享进程的资源,会产生竞态条件,在某些情况下需要协调指令执行的先后顺序,也就是实现线程同步。
下面是一个常见的多线程累加程序,由于sum++并不是一个原子操作,所以多个线程互相抢占从而造成计算错误。
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
int sum = 0;
void* add(void* arg){
for (int i = 0; i < 10000000; ++i){
sum++;
}
}
int main(){
pthread_t id;
for (int i = 0; i < 10; ++i){
int ret = pthread_create(&id, NULL, add, NULL);
if(0 != ret){
printf("Failed to create thread!\n");
return -1;
}
}
sleep(10);
printf("%d\n", sum);
return 0;
}
sum 的最终值应该为 100000000,但是上述代码并不会得到我们想要的结果。

2 互斥锁
解决的办法是每次只允许一个线程执行 sum++ ,在 sum++ 处加入互斥锁,上述的代码可以改写为:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
int sum = 0;
pthread_mutex_t mutex;
void* add(void* arg){
for (int i = 0; i < 10000000; ++i){
pthread_mutex_lock(&mutex);
sum++;
pthread_mutex_unlock(&mutex);
}
}
int main(){
pthread_t id;
pthread_mutex_init(&mutex, NULL);
for (int i = 0; i < 10; ++i){
int ret = pthread_create(&id, NULL, add, NULL);
if(0 != ret){
printf("Failed to create thread!\n");
return -1;
}
}
sleep(10);
printf("%d\n", sum);
return 0;
}
这样就可以稳定的得到 100000000 的结果:

3 POSIX信号量
接下来使用 POSIX 信号量来解决:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
#include<semaphore.h>
int sum = 0;
sem_t sem;
void* add(void* arg){
int tmp = 0;
for (int i = 0; i < 10000000; ++i){
tmp++;
}
sem_wait(&sem);
sum += tmp;
sem_post(&sem);
}
int main(){
pthread_t id;
sem_init(&sem, 0, 1);
for (int i = 0; i < 10; ++i){
int ret = pthread_create(&id, NULL, add, NULL);
if(0 != ret){
printf("Failed to create thread!\n");
return -1;
}
}
sleep(10);
printf("%d\n", sum);
return 0;
}

浙公网安备 33010602011771号