多线程编程,基于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