int count = 0;
void * add(void *arg){
int val,i;
for(i = 0;i< 5000;i ++){
val = count;
printf("%p: %d\n",pthread_self(),val);
count = val + 1;
}
return nullptr;
}
int main(){
pthread_t tida,tidb;
pthread_create(&tida,NULL,add,NULL);
pthread_create(&tidb,NULL,add,NULL);
pthread_join(tida,NULL);
pthread_join(tidb,NULL);
return 0;
}
两个线程同时跑,最后的结果是4999,并不是我们想象中的10000。这是为什么呢?多个线程访问和修改了全局变量count
,而这个变量没有被任何同步机制保护。在并发执行的情况下,多个线程可能会同时读取和修改count
变量的值,从而导致竞态条件的发生。具体来说,当两个线程同时读取count
变量的值并保存到本地变量中时,它们得到的可能是相同的值。接着两个线程分别将本地变量加1,并写回到count
变量中。这样就会出现一个线程的修改被覆盖的情况,导致最终结果小于预期值。
因此,为了避免竞态条件,需要使用同步机制来保护多个线程对共享资源的访问,例如使用互斥锁、信号量等机制。这些同步机制可以确保每次只有一个线程能够访问和修改共享资源,从而避免多个线程同时修改同一个资源的情况,从而保证程序的正确性和可预测性。
对于多线程的程序,访问冲突是很普遍的,解决方法是引入互斥锁(MUtex,MutualExclusive Lock),获得锁的线程可以完成”读-修改-写“的操作,然后释放锁给其他的线程,没有获得所得线程只能等待而不能访问共享数据,这样”读-修改-写"三步操作组成一个原子操作,要么都执行,要么都不执行,不会执行到中间被打断,也不会在其他处理器上并行做这个操作
int count = 0;
pthread_mutex_t add_mux = PTHREAD_MUTEX_INITIALIZER;
void * add(void *arg){
int val,i;
for(i = 0;i< 5000;i ++){
pthread_mutex_lock(&add_mux);
val = count;
printf("%p: %d\n",pthread_self(),val);
count = val + 1;
pthread_mutex_unlock(&add_mux);
}
return nullptr;
}
int main(){
pthread_t tida,tidb;
pthread_create(&tida,NULL,add,NULL);
pthread_create(&tidb,NULL,add,NULL);
pthread_join(tida,NULL);
pthread_join(tidb,NULL);
return 0;
}
typedef struct Goods {
int data;
struct Goods *next;
} Goods;
Goods *head = NULL;
pthread_mutex_t mutex_head = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t have_good_cond = PTHREAD_COND_INITIALIZER;
void *producer(void *) {
Goods *newGood;
while (1) {
newGood = (Goods *) malloc(sizeof(Goods));
newGood->data = rand() % 100;
// 头插法
pthread_mutex_lock(&mutex_head);
newGood->next = head;
head = newGood;
pthread_mutex_unlock(&mutex_head);
pthread_cond_signal(&have_good_cond);
printf("produce %d\n", newGood->data);
sleep(rand() % 3);
}
}
void *consumer(void *) {
Goods *k;
while (1) {
pthread_mutex_lock(&mutex_head);
if (!head) {
pthread_cond_wait(&have_good_cond, &mutex_head);
}
k = head;
head = head->next;
pthread_mutex_unlock(&mutex_head);
printf("consume %d\n", k->data);
free(k);
sleep(rand() % 3);
}
}
pthread_t produceThread, consumerThread;
int main() {
srand(time(nullptr));
pthread_create(&produceThread, nullptr, producer, nullptr);
pthread_create(&consumerThread, nullptr, consumer, nullptr);
pthread_join(produceThread, NULL);
pthread_join(consumerThread, NULL);
return 0;
}