• Windows 多线程编程 C语言


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

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

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. int number = -1; //定义全局变量
    6. CRITICAL_SECTION Critical;//定义临界区句柄
    7. int a[4][4]={8,7,6,5,4,3,2,1,18,7,16,15,14,13,21,11};
    8. void print(int *a,int size){
    9. for (int i = 0 ;i < size; i++){
    10. printf("%d ",a[i]);
    11. a[i] = a[i]+1;
    12. }
    13. }
    14. unsigned long __stdcall ThreadProc1(void* lp) {
    15. EnterCriticalSection(&Critical);
    16. printf("thread %d : %d\n",number,number);
    17. ++number;
    18. int numTmp=number;
    19. Sleep(100);
    20. LeaveCriticalSection(&Critical);
    21. print(a[numTmp],4);
    22. return 0;
    23. }
    24. int main() {
    25. InitializeCriticalSection(&Critical); //初始化临界区对象
    26. for(int i = 0;i < 4;i++){
    27. HANDLE Thread;
    28. DWORD dwThreadId;
    29. Thread=::CreateThread
    30. (NULL,0,ThreadProc1,NULL,0,&dwThreadId);
    31. printf("The new thread ID is : %d \n",dwThreadId);
    32. ::WaitForSingleObject(Thread,INFINITE);
    33. ::CloseHandle(Thread);
    34. }
    35. //Sleep(10*1000);
    36. printf("\nhello begin\n");
    37. for(int i = 0;i < 4; i++){
    38. for(int j = 0;j < 4;j++){
    39. printf("%d ",a[i][j]);
    40. }
    41. printf("\n");
    42. }
    43. printf("hello end\n");
    44. return 0;
    45. }

    上面的代码,试着删除::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)。

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. #define MAX_NUMBER 10000000
    6. CRITICAL_SECTION Critical;//定义临界区句柄
    7. int number = 1;
    8. unsigned long __stdcall ThreadProc1(void* lp) {
    9. while (number < MAX_NUMBER) {
    10. if (number < MAX_NUMBER)
    11. EnterCriticalSection(&Critical);
    12. //cout << "thread 1 :"<
    13. ++number;
    14. //Sleep(100);
    15. LeaveCriticalSection(&Critical);
    16. }
    17. return 0;
    18. }
    19. unsigned long __stdcall ThreadProc2(void* lp) {
    20. while (number < MAX_NUMBER) {
    21. if (number < MAX_NUMBER)
    22. EnterCriticalSection(&Critical);
    23. //cout << "thread 2 :"<
    24. ++number;
    25. //Sleep(100);
    26. LeaveCriticalSection(&Critical);
    27. }
    28. return 0;
    29. }
    30. int main() {
    31. InitializeCriticalSection(&Critical); //初始化临界区对象
    32. //CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
    33. //CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);
    34. HANDLE ThreadOne[2];
    35. DWORD dwThreadIdOne;
    36. ThreadOne[0] = ::CreateThread(NULL, 0, ThreadProc1, NULL, 0, &dwThreadIdOne);
    37. printf("\n\nThe new thread ID is : %d \n", dwThreadIdOne);
    38. //::CloseHandle(ThreadOne);
    39. //HANDLE ThreadTwo;
    40. DWORD dwThreadIdTwo;
    41. ThreadOne[2] = ::CreateThread(NULL, 0, ThreadProc2, NULL, 0, &dwThreadIdTwo);
    42. printf("The new thread ID is : %d \n", dwThreadIdTwo);
    43. //::WaitForSingleObject(ThreadTwo, INFINITE);
    44. //::CloseHandle(ThreadTwo);
    45. //Sleep(10*1000);
    46. for(int i = 0 ;i < 2;i++)
    47. ::WaitForSingleObject(ThreadOne[i], INFINITE);
    48. for(int i = 0;i < 2;i++)
    49. ::CloseHandle(ThreadOne[i]);
    50. printf("\nhello start\n");
    51. printf("number: %d\n",number);printf("number: %d\n",number);printf("number: %d\n",number);printf("number: %d\n",number);
    52. return 0;
    53. }

    写之前添加范围判断语句

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. #define MAX_NUMBER 10000000
    6. CRITICAL_SECTION Critical;//定义临界区句柄
    7. int number = 1;
    8. unsigned long __stdcall ThreadProc1(void* lp) {
    9. while (number < MAX_NUMBER) {
    10. if (number < MAX_NUMBER)
    11. EnterCriticalSection(&Critical);
    12. //cout << "thread 1 :"<
    13. if (number < MAX_NUMBER) ++number;
    14. //Sleep(100);
    15. LeaveCriticalSection(&Critical);
    16. }
    17. return 0;
    18. }
    19. unsigned long __stdcall ThreadProc2(void* lp) {
    20. while (number < MAX_NUMBER) {
    21. if (number < MAX_NUMBER)
    22. EnterCriticalSection(&Critical);
    23. //cout << "thread 2 :"<
    24. if (number < MAX_NUMBER) ++number;
    25. //Sleep(100);
    26. LeaveCriticalSection(&Critical);
    27. }
    28. return 0;
    29. }
    30. int main() {
    31. InitializeCriticalSection(&Critical); //初始化临界区对象
    32. //CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
    33. //CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);
    34. HANDLE ThreadOne[2];
    35. DWORD dwThreadIdOne;
    36. ThreadOne[0] = ::CreateThread(NULL, 0, ThreadProc1, NULL, 0, &dwThreadIdOne);
    37. printf("\n\nThe new thread ID is : %d \n", dwThreadIdOne);
    38. //::CloseHandle(ThreadOne);
    39. //HANDLE ThreadTwo;
    40. DWORD dwThreadIdTwo;
    41. ThreadOne[2] = ::CreateThread(NULL, 0, ThreadProc2, NULL, 0, &dwThreadIdTwo);
    42. printf("The new thread ID is : %d \n", dwThreadIdTwo);
    43. //::WaitForSingleObject(ThreadTwo, INFINITE);
    44. //::CloseHandle(ThreadTwo);
    45. //Sleep(10*1000);
    46. for(int i = 0 ;i < 2;i++)
    47. ::WaitForSingleObject(ThreadOne[i], INFINITE);
    48. for(int i = 0;i < 2;i++)
    49. ::CloseHandle(ThreadOne[i]);
    50. printf("\nhello start\n");
    51. printf("number: %d\n",number);printf("number: %d\n",number);printf("number: %d\n",number);printf("number: %d\n",number);
    52. return 0;
    53. }

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

  • 相关阅读:
    进程创建时自动打开的三个文件描述符
    改进的最大内切圆算法求裂缝轮廓宽度
    前端基础知识点:JS中的参数传递详解
    动态规划(子序列问题)
    vscode中格式化C++代码缩进的方法
    【TensorFlow深度学习】创建与操作张量的典型实践与技巧
    Hadoop根据加工数据量计算Datanode数量
    [MRCTF2020]套娃
    Excel VSTO开发4 -其他事件
    ML.NET相关资源整理
  • 原文地址:https://blog.csdn.net/weixin_54010759/article/details/126126610