需求:使用10个线程,同时对一个值count进行加一操作,每个线程对count加100000次,最终使得count=1000000
第一版代码:不加锁
lock.c
#include<stdio.h>
#include<pthread.h>#define THREAD_COUNT 10void *thread_callback(void *arg){int *pcount=(int*)arg;int i=0;while(i++ < 100000){(*pcount)++;usleep(1);//休眠一毫秒}
}int main(){pthread_t threadid[THREAD_COUNT]={0};//定义多线程int i=0;int count=0;for(i=0;i<THREAD_COUNT;i++){pthread_create(&threadid[i],NULL,thread_callback,&count);}//每隔一秒打印一次count值for(i=0;i<100;i++){printf("count: %d\n",count);sleep(1);//休眠一秒}return 0;
}
在Linux环境下编译执行:
编译: gcc -o lock lock.c -pthread
执行: ./lock
运行结果:
在不加锁的情况之下,使用多线程无法满足需求,即count值无法加到1000000.
从代码分析唯一能改变count值得代码是:count++,源代码中为:(*pcount)++
count++转化为汇编语言为:
正常情况(预期情况):每一个线程的count++都执行完再执行另外一个线程的count++
eax:寄存器
不正常情况(实际情况):当前线程中count++没完全执行完就跳转到另外一个线程执行
线程在执行代码的过程中被打断,这样所带来的的结果就是两个线程中执行两次count++,但count实际值只加了1,使得结果不能达到我们所预期的1000000值.
解决方法:加锁,使得每个线程在执行是不被打断,即不会出现不正常情况.
第二版代码:这里使用互斥锁(mutex),也可以使用自旋锁(spinlock)
#include<stdio.h>
#include<pthread.h>#define THREAD_COUNT 10pthread_mutex_t mutex;//定义一个锁void *thread_callback(void *arg){int *pcount=(int*)arg;int i=0;while(i++ < 100000){#if 0(*pcount)++;#elsepthread_mutex_lock(&mutex);//上锁(*pcount)++;pthread_mutex_unlock(&mutex);//解锁#endifusleep(1);//休眠一毫秒}
}int main(){pthread_t threadid[THREAD_COUNT]={0};//定义多线程pthread_mutex_init(&mutex,NULL);//初始化锁,NULL为系统默认int i=0;int count=0;for(i=0;i<THREAD_COUNT;i++){pthread_create(&threadid[i],NULL,thread_callback,&count);}for(i=0;i<100;i++){printf("count: %d\n",count);sleep(1);//休眠一秒}return 0;
}
运行结果: