线程并发执行带来的问题
2010-05-25 22:17
197 查看
线程并发会引发一些难以发现的错误,现在就来看一个简单的线程的并发导致的问题,首先来看下面程序,程序很简单,就是创建了3个线程,第一个线程对i和count加1,第二个线程对j和count加1,第三个线程对k和count加1,i,j,k,count初始化都为0,这样的华,按照逻辑来说,最后i+j+k = count:
在我机子上执行的结果是:
i = 92394160, j = 55544601, k= 42663454, count = 74003307
i+j+k=190606856
很明显,i+j+k != count,为什么会发生这样的问题呢?首先我们可以肯定的是,按照数学逻辑上讲,本文一开始的假定(i+j+k = count)是正确的,但是执行结果却出乎我们的意料,或许,问题就出在线程的并发执行上。再来仔细分析下创建的线程执行的操作,3个线程中都对count进行了++操作,++操作在C语言中看起来是一条语句,实际上编译后是3条语句,首先将count的值写入寄存器,然后对其进行加1操作,在接着将寄存器的值读出,保存在count中。现在来再看看这个程序,三个线程简称为A、B、C,如果A刚刚把count的值写入寄存器中,此时调度程序调度B线程开始运行,这个时候,B对count进行了N次加法操作,此时count = count+N,此时调度程序恢复执行A线程,那么此时A中保存的count的值却是是B线程执行前的值,此时,A再对count进行操作时,就是基于旧的值(其他线程对count进行操作前的值),而不是最新的值,所以count的值并不是我们期望中的值。
一个小小的并发程序,却也引出了这样的一个问题,所以在遇到并发程序时,最好先想想怎么样利用同步和互斥操作来避免这样的错误。错误之处,还轻您斧正。先谢谢啦。
#include<stdio.h> #include<stdlib.h> #include<pthread.h> int count = 0; int i = 0; int j = 0; int k = 0; /*给i的值和count的值加1*/ void *modify_i_thread(void *data) { for(;;) { i++; count++; } } /*给j的值和count的值加1*/ void *modify_j_thread(void *data) { for(;;) { j++; count++; } } /*给k的值和count的值加1*/ void *modify_k_thread(void *data) { for(;;) { k++; count++; } } int main(void) { pthread_t pthid; /*创建三个线程 */ pthread_create(&pthid, NULL, modify_i_thread, NULL); pthread_create(&pthid, NULL, modify_j_thread, NULL); pthread_create(&pthid, NULL, modify_k_thread, NULL); sleep(1); /*打印结果 */ printf("i = %d, j = %d, k= %d, count = %d\n", i, j, k, count); printf("i+j+k=%d\n", i + j + k); return 0; }
在我机子上执行的结果是:
i = 92394160, j = 55544601, k= 42663454, count = 74003307
i+j+k=190606856
很明显,i+j+k != count,为什么会发生这样的问题呢?首先我们可以肯定的是,按照数学逻辑上讲,本文一开始的假定(i+j+k = count)是正确的,但是执行结果却出乎我们的意料,或许,问题就出在线程的并发执行上。再来仔细分析下创建的线程执行的操作,3个线程中都对count进行了++操作,++操作在C语言中看起来是一条语句,实际上编译后是3条语句,首先将count的值写入寄存器,然后对其进行加1操作,在接着将寄存器的值读出,保存在count中。现在来再看看这个程序,三个线程简称为A、B、C,如果A刚刚把count的值写入寄存器中,此时调度程序调度B线程开始运行,这个时候,B对count进行了N次加法操作,此时count = count+N,此时调度程序恢复执行A线程,那么此时A中保存的count的值却是是B线程执行前的值,此时,A再对count进行操作时,就是基于旧的值(其他线程对count进行操作前的值),而不是最新的值,所以count的值并不是我们期望中的值。
一个小小的并发程序,却也引出了这样的一个问题,所以在遇到并发程序时,最好先想想怎么样利用同步和互斥操作来避免这样的错误。错误之处,还轻您斧正。先谢谢啦。
相关文章推荐
- 事务和线程的区别还有事务并发执行引起的四个问题:丢失修改、脏读、不可重复读,幻读
- 并发问题和主线程等待所有子线程运行完毕再执行
- Java线程---休眠问题来看并发执行
- java并发实战--java线程的带来的问题
- [MySQL]对于事务并发处理带来的问题,脏读、不可重复读、幻读的理解
- java并发系列:一线程常见问题
- Spring并发访问的线程安全性问题
- Spring并发访问的线程安全性问题
- 数据库并发操作带来的问题以及解决方案
- 数据库中的并发操作带来的一系列问题及解决方法
- 关于线程并发访问全局变量问题
- Springmvc 并发访问的线程安全性问题
- Spring并发访问的线程安全性问题
- Spring并发访问的线程安全性问题
- CountDownLatch使用countDown方法来触发其他等待线程再执行的问题
- Spring MVC并发访问的线程安全性问题
- 【数据库】数据库并发操作(一)数据库并发操作带来的问题
- 数据库---并发控制及其带来的问题丢失修改,读脏数据,不可重复读及解决(程序员级)
- 并发事务处理带来的问题
- 数据库事务并发带来的问题、及并行