需求:使用10个线程,同时对一个值count进行加一操作,每个线程对count加100000次,最终使得count=1000000
第一版代码:不加锁
lock.c
#include<stdio.h> #include<pthread.h> #define THREAD_COUNT 10 void *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)
#include<stdio.h> #include<pthread.h> #define THREAD_COUNT 10 pthread_mutex_t mutex;//定义一个锁 void *thread_callback(void *arg){ int *pcount=(int*)arg; int i=0; while(i++ < 100000){ #if 0 (*pcount)++; #else pthread_mutex_lock(&mutex);//上锁 (*pcount)++; pthread_mutex_unlock(&mutex);//解锁 #endif usleep(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; }
运行结果: