为什么sum这里要临界区?
先请看代码:
#include <windows.h>
#include <stdio.h>
#include <time.h>
static long num_steps=1000000000;
const int gNumThreads = 2;
double step = 0.0;
double pi = 0.0,sum = 0.0;
CRITICAL_SECTION gCS;
DWORD WINAPI threadFunction(LPVOID pArg)
{
int myNum = *((int *)pArg);
double partialSum = 0.0, x; // local to each thread
for ( int i=myNum; i<num_steps; i+=gNumThreads )
{
x = (i+0.5)*step;
partialSum = partialSum + 4.0/(1.0 + x*x); //compute partial sums at each thread
}
EnterCriticalSection(&gCS);
sum += partialSum; // add partial to global final answer
LeaveCriticalSection(&gCS);
return 0;
}
int main()
{
clock_t start ,stop ;
start = clock() ;
InitializeCriticalSection(&gCS) ;
HANDLE hThreads[gNumThreads] ;
int tNum[gNumThreads];
step = 1.0/(double) num_steps;
for(int i=0; i<gNumThreads; i++){
tNum[i] = i ;
hThreads[i] = CreateThread( NULL,
0,
threadFunction,
&tNum[i],
0,
NULL);
}
WaitForMultipleObjects(gNumThreads,hThreads,TRUE,INFINITE) ;
DeleteCriticalSection(&gCS) ;
printf("sum = %12.9lf\n",sum) ;
pi = step * sum ;
stop = clock() ;
printf("pi=%12.9lf\n",pi) ;
printf("The time of calculation was %f seconds\n",((double)(stop - start)/1000.0));
system("pause") ;
return 0 ;
}
这段代码里,为什么在sum += partialSum;处要用临界区,
我个人觉得,不是函数的话,不就不用临界区么?因为我个人觉得此时只要时间片没完,线程就一直是一个啊?
难道是因为sum是全局变量的原因?
【注:我是初学多线程!】
[解决办法]
全局变量用临界区是对的.
你说的 "不是函数的话,不就不用临界区" 什么意思? 是要在调用其它函数的时候才使用临界区?
时间片和线程个数又有什么关系了?
[解决办法]
难道是因为sum是全局变量的原因?
没错,多线程访问全局变量,需要临界区。
[解决办法]
线程在执行的时候不能保证每次的函数体全部都跑完, 线程切换由CPU时间片控制, 基本可以认为是任意时刻都会发生跳转, 所以加上临界区, 保证一个线程写入的时候不会受到其他线程干扰
[解决办法]
你无法知道线程的切换会在什么时候出现,虽然你的两个线程是使用同一个函数,但是对于两个线程而言,就像在运行两个不同的函数一样,由系统实现调度。两个线程对同一个全局变量进行了操作,所以需要使用临界区来实现线程的同步。
sum += partialSum; 实际上是由多条机器指令实现的,有可能线程1在执行其中一条机器指令时,出现了线程的切换,导致线程2也对sum进行了操作,这就会出现错误。
[解决办法]
栈是一个线程一个的, 函数进入退出不会切换栈, 只是操作栈顶的数据.
切换线程时系统会把栈切换好, 两个线程执行同一个函数时他们的栈是不一样的, 局部变量在栈里面, 所以局部变量不会有冲突. 而全局变量多个线程同时写入就会有冲突.
------解决方案--------------------
partialSum是局部变量,不是共享资源,局部变量会独立分配在各自的线程栈中,互不影响。全局变量是所有线程都可以访问的,所以要进行线程的同步。