Windows 多线程编程 C语言

Windows 多线程编程 C语言下面的代码,目的是将number加到MAX_NUMBER即可,由于是两个线程并行,总会多加一个1(若是10个线程并行,则会多加9,原因同理,当某一个线程将number的值加到MAX_NUMBER之后,其他9个线程被阻塞,但是都有写权限,又在写之前并没有number值的范围判断,导致每个线程都再次对number加1)。上述代码采用的是临界区句柄进行互斥判断,在使用信号量进行互斥控制时,发现意图是使用多线程,但实际上只用首先被创建的线程在进行工作,其他线程均为进行工作,待定。写之前添加范围判断语句。…

多线程编程,基于Windows,语言是C语言。

在<windows.h>中包含多线程的相关函数等,无需再次下载库或者文件。

#include<windows.h>
#include<iostream>
#include <stdio.h>
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<windows.h>
#include<iostream>
#include <stdio.h>
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 << endl;
		++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 << endl;
		++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<windows.h>
#include<iostream>
#include <stdio.h>
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 << endl;
		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 :"<<number << endl;
		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;
}

上述代码采用的是临界区句柄进行互斥判断,在使用信号量进行互斥控制时,发现意图是使用多线程,但实际上只用首先被创建的线程在进行工作,其他线程均为进行工作,待定。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/38475.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注