線程之路二:線程原子操作和線程CriticalSection操作

一原子操作:即是那種運行了不把這條語句執行完就不會把計算機控制權交給另一個線程控制

#include <iostream>
#include<Windows.h>
#include <process.h>

int num=0;

unsigned int __stdcall ThreadFun(PVOID pm)
{
	InterlockedIncrement((LPLONG)&num);  //原子操作
	//std::cout<<"第"<<*((int*)pm)<<"線程PID:"<<GetCurrentThreadId()<<"說:"<<num<<std::endl;
	return 0;
}

int main()
{
	const int n =100;
	int m =10;
	unsigned int a[n];
	HANDLE handle[n];
	while(m){
		num=0;
		for(int i=0;i<n;i++){

			handle[i] =(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,&a[i]);
		}
		WaitForMultipleObjects(n,handle,true,INFINITE);
		m--;
		std::cout<<num<<std::endl;
	}
	/*for(int j=0;j<n;j++)
	std::cout<<a[j]<<std::endl;*/
	system("pause");
	return 0;
}

結果如下:

這裏你也許會問爲什麼不全是100;答案多線程;主進程不等每次while循環中的100線程執行完,就進行下一次的100個線程了,也許上一次只有56個線程執行完畢,此時num=55,而進入下一循環就會置0;此時前100次中的五十六次算白執行了,也就爲什麼會有大於和小於100的情況了

在每次while中不置0,代碼:

#include <iostream>
#include<Windows.h>
#include <process.h>
#include <stdio.h> 

int num=0;

unsigned int __stdcall ThreadFun(PVOID pm)
{
	InterlockedIncrement((LPLONG)&num);  //原子操作
	//std::cout<<"第"<<*((int*)pm)<<"線程PID:"<<GetCurrentThreadId()<<"說:"<<num<<std::endl;
	return 0;
}

int main()
{
	const int n =100;
	int m =10;
	unsigned int a[n];
	HANDLE handle[n];
	while(m){
		for(int i=0;i<n;i++){

			handle[i] =(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,&a[i]);
		}
		WaitForMultipleObjects(n,handle,true,INFINITE);
		m--;
		std::cout<<num<<std::endl;
	}
	/*for(int j=0;j<n;j++)
	std::cout<<a[j]<<std::endl;*/
	Sleep(10000);//等待所有線程執行完畢
	std::cout<<num<<std::endl;
	system("pause");
	return 0;
}


此時結果出現1000!

 

不用原子操作  改成num++ 會出現結果:

不一定爲1000

二CriticalSection操作

#include <iostream>
#include<Windows.h>
#include <process.h>

CRITICAL_SECTION a,b;
int num;
unsigned int __stdcall ThreadFun(PVOID pm)
{
	LeaveCriticalSection(&a);
	EnterCriticalSection(&b);
	num++;
		std::cout<<*((int*)pm)<<"說:"<<num<<std::endl;
	LeaveCriticalSection(&b);
	return 0;
}

int main()
{
	const int n =50;
	HANDLE handle[n];

	InitializeCriticalSection(&a);
	InitializeCriticalSection(&b);
	num = 0;
	int i=0;
	while(i<10){
		EnterCriticalSection(&a);
		handle[i] =(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,NULL);
		i++;
	}
	WaitForMultipleObjects(n,handle,true,INFINITE);
	system("pause");
	return 0;
}

結果爲:

但此時傳入的值不對,這個原因主要是主進程調用到這句話時

handle[i] =(HANDLE)_beginthreadex(NULL,0,ThreadFun,&i,0,NULL);

線程不一定在這個之後去運行函數

unsigned int __stdcall ThreadFun(PVOID pm)

這是不能同步的

介紹下旋轉鎖:

//等待訪問這個資源,不停的假裝告訴系統我正在使用這個資源
  //但是,是通過InterlockedExchange這個原子函數告訴系統的,
 //這意味着如果這個資源正被別的線程使用的時候,CPU不會讓這件事變爲事實
   //但是呢如果,沒線程使用訪問改變量的話,當前線程就得逞了。
   //看來主動一些就會有收穫的,
   //接下來這個非常主動的線程將要跳出辛苦的循環請求過程享受他的成果了
   while(InterlockedExchange(&g_fResourceInUse, TRUE) == TRUE)
     Sleep(0);
   //訪問剛佔有的資源
 //Access the resource.


 

InitializeCriticalSectionAndSpinCount(&b,4000);//旋轉鎖 旋轉4000次


其他的跟CriticalSection一樣

下回合再說

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章