线程同步
所谓线程同步,就是有多个线程共享相同的内存时,需要确保共享数据在每个线程中都是一致的。若同一个共享变量在两个及以上线程中所显示的结果是不一样的,就表明线程不同步。
什么情况下需要使用线程同步?
当一个线程可以修改的变量,其它线程也可以读取或修改的时候,必须进行线程同步,否则可能导致错误。
假设有两个线程A和B,需要对整型全局变量i进行递增操作,过程如下所示:
递增操作不是原子操作,编译器完成递增操作实际上需要3条机器指令:
(1)将变量从内存单元读入寄存器;
(2)在寄存器中对变量进行增量操作;
(3)把寄存器中新的值写回到内存单元。
两个线程在进行递增操作时,有可能出现如下图所示情况,
1、线程A运行,把变量i的值(5)读入到线程A的寄存器中;
2、线程A的寄存器内容进行增量操作,寄存器的值变为6;与此同时,线程B运行,将变量i的值读入到线程B的寄存器中,由于线程A的寄存器的值还未写回内存单元,因此读入到线程B的寄存器的值仍为5。
3、将线程A寄存器的值写回内存单元,变量i的值变为6;与此同时,线程B的寄存器内容进行增量操作,其寄存器的值变为6;
4、将线程B寄存器的值写回内存单元,变量i的值变为6;
从上述步骤可以看出,经过两次递增操作之后,变量i的值并没有从5变为7,而是从5变为6,产生了错误的结果。写两个线程递增一个全局变量的情境验证,如下:
#include<stdio.h>
#include<pthread.h>
#defeine NUMLOOP 20
int i=0;
void* threadFunc(void* vptr)
{
int k;
for (k=0;k<NUMLOOP;k++)
{
++i;
printf("B %ld:%d\n",pthread_self(),i);
}
}
int main()
{
pthread_t tidB;
pthread_create(&tidB,NULL,&threadFunc,NULL): //创建子线程B
//假设主线程为线程A
for (int k=0;k<NUMLOOP;k++)
{
++i;
printf("A %ld:%d\n",pthread_self(),i);
}
pthread_join(tidB