多线程编程,基于Windows,语言是C语言。
在
- #include
- #include
- #include
- using namespace std;
-
- int number = -1; //定义全局变量
- CRITICAL_SECTION Critical;//定义临界区句柄
- int a[4][4]={8,7,6,5,4,3,2,1,18,7,16,15,14,13,21,11};
- void print(int *a,int size){
- for (int i = 0 ;i < size; i++){
- printf("%d ",a[i]);
- a[i] = a[i]+1;
- }
- }
- unsigned long __stdcall ThreadProc1(void* lp) {
- EnterCriticalSection(&Critical);
- printf("thread %d : %d\n",number,number);
- ++number;
- int numTmp=number;
- Sleep(100);
- LeaveCriticalSection(&Critical);
- print(a[numTmp],4);
- return 0;
- }
-
- int main() {
-
- InitializeCriticalSection(&Critical); //初始化临界区对象
- for(int i = 0;i < 4;i++){
- HANDLE Thread;
- DWORD dwThreadId;
- Thread=::CreateThread
- (NULL,0,ThreadProc1,NULL,0,&dwThreadId);
- printf("The new thread ID is : %d \n",dwThreadId);
- ::WaitForSingleObject(Thread,INFINITE);
- ::CloseHandle(Thread);
- }
- //Sleep(10*1000);
- printf("\nhello begin\n");
- for(int i = 0;i < 4; i++){
- for(int j = 0;j < 4;j++){
- printf("%d ",a[i][j]);
- }
- printf("\n");
- }
-
- printf("hello end\n");
- return 0;
- }
-
上面的代码,试着删除::WaitForSingleObject(Thread,INFINITE);语句后,再次运行,看结果(多线程是异步的,利用该语句,强制要求线程运行完成后再返回)。如果不对线程进行同步处理,会导致后续读取前面并行线程产生的变量值是错误值(因为前面的线程可能并没有全部按照既定规则更新所有变量的值)。
下面举一例子,要求使用两个线程,对一个变量number进行加1操作,加到100即停止,number的初始值是1.显然,我们要用到信号量互斥机制,或者类似机制,保证同一时刻只能有一个进程对number进行写操作,但是,请注意,阻塞只是将线程阻塞了,保证的只是该时刻只有一个线程有写权限,被阻塞的线程在下一时刻仍有写的权限,具体来说,创建的两个线程thread1和thread2,如果在thread2正在将number加到100,此时另一个线程thread1必被阻塞,无法对number进行写操作,但是当线程thread2写完成后,线程thread1立刻解除阻塞,拥有对number的写权限,自然将number再次加一,number变为101,可见单纯设置信号量等无法实现多线程下number准确加到某一定值,对此,可以在每次获得写权限时,在写操作之前再次进行number范围判断。
下面的代码,目的是将number加到MAX_NUMBER即可,由于是两个线程并行,总会多加一个1(若是10个线程并行,则会多加9,原因同理,当某一个线程将number的值加到MAX_NUMBER之后,其他9个线程被阻塞,但是都有写权限,又在写之前并没有number值的范围判断,导致每个线程都再次对number加1)。
- #include
- #include
- #include
- using namespace std;
- #define MAX_NUMBER 10000000
- CRITICAL_SECTION Critical;//定义临界区句柄
- int number = 1;
-
- unsigned long __stdcall ThreadProc1(void* lp) {
- while (number < MAX_NUMBER) {
- if (number < MAX_NUMBER)
- EnterCriticalSection(&Critical);
- //cout << "thread 1 :"<
- ++number;
- //Sleep(100);
- LeaveCriticalSection(&Critical);
- }
-
- return 0;
- }
-
- unsigned long __stdcall ThreadProc2(void* lp) {
- while (number < MAX_NUMBER) {
- if (number < MAX_NUMBER)
- EnterCriticalSection(&Critical);
- //cout << "thread 2 :"<
- ++number;
- //Sleep(100);
- LeaveCriticalSection(&Critical);
- }
-
- return 0;
- }
-
- int main() {
-
- InitializeCriticalSection(&Critical); //初始化临界区对象
- //CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
- //CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);
- HANDLE ThreadOne[2];
- DWORD dwThreadIdOne;
- ThreadOne[0] = ::CreateThread(NULL, 0, ThreadProc1, NULL, 0, &dwThreadIdOne);
- printf("\n\nThe new thread ID is : %d \n", dwThreadIdOne);
-
- //::CloseHandle(ThreadOne);
-
- //HANDLE ThreadTwo;
- DWORD dwThreadIdTwo;
- ThreadOne[2] = ::CreateThread(NULL, 0, ThreadProc2, NULL, 0, &dwThreadIdTwo);
- printf("The new thread ID is : %d \n", dwThreadIdTwo);
- //::WaitForSingleObject(ThreadTwo, INFINITE);
- //::CloseHandle(ThreadTwo);
-
- //Sleep(10*1000);
-
- for(int i = 0 ;i < 2;i++)
- ::WaitForSingleObject(ThreadOne[i], INFINITE);
-
- for(int i = 0;i < 2;i++)
- ::CloseHandle(ThreadOne[i]);
- printf("\nhello start\n");
- printf("number: %d\n",number);printf("number: %d\n",number);printf("number: %d\n",number);printf("number: %d\n",number);
- return 0;
- }
-
写之前添加范围判断语句
- #include
- #include
- #include
- using namespace std;
- #define MAX_NUMBER 10000000
- CRITICAL_SECTION Critical;//定义临界区句柄
- int number = 1;
-
- unsigned long __stdcall ThreadProc1(void* lp) {
- while (number < MAX_NUMBER) {
- if (number < MAX_NUMBER)
- EnterCriticalSection(&Critical);
- //cout << "thread 1 :"<
- if (number < MAX_NUMBER) ++number;
- //Sleep(100);
- LeaveCriticalSection(&Critical);
- }
-
- return 0;
- }
-
- unsigned long __stdcall ThreadProc2(void* lp) {
- while (number < MAX_NUMBER) {
- if (number < MAX_NUMBER)
- EnterCriticalSection(&Critical);
- //cout << "thread 2 :"<
- if (number < MAX_NUMBER) ++number;
- //Sleep(100);
- LeaveCriticalSection(&Critical);
- }
-
- return 0;
- }
-
- int main() {
-
- InitializeCriticalSection(&Critical); //初始化临界区对象
- //CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
- //CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);
- HANDLE ThreadOne[2];
- DWORD dwThreadIdOne;
- ThreadOne[0] = ::CreateThread(NULL, 0, ThreadProc1, NULL, 0, &dwThreadIdOne);
- printf("\n\nThe new thread ID is : %d \n", dwThreadIdOne);
-
- //::CloseHandle(ThreadOne);
-
- //HANDLE ThreadTwo;
- DWORD dwThreadIdTwo;
- ThreadOne[2] = ::CreateThread(NULL, 0, ThreadProc2, NULL, 0, &dwThreadIdTwo);
- printf("The new thread ID is : %d \n", dwThreadIdTwo);
- //::WaitForSingleObject(ThreadTwo, INFINITE);
- //::CloseHandle(ThreadTwo);
-
- //Sleep(10*1000);
-
- for(int i = 0 ;i < 2;i++)
- ::WaitForSingleObject(ThreadOne[i], INFINITE);
-
- for(int i = 0;i < 2;i++)
- ::CloseHandle(ThreadOne[i]);
- printf("\nhello start\n");
- printf("number: %d\n",number);printf("number: %d\n",number);printf("number: %d\n",number);printf("number: %d\n",number);
- return 0;
- }
-
上述代码采用的是临界区句柄进行互斥判断,在使用信号量进行互斥控制时,发现意图是使用多线程,但实际上只用首先被创建的线程在进行工作,其他线程均为进行工作,待定。