zoukankan      html  css  js  c++  java
  • [一个经典的多线程同步问题]问题引入

    下面来看一个经典的多线程的同步和互斥的问题,问题的描述:

    主线程启动10个子线程并将表示子线程序号的变量的地址作为参数传递给子线程。子线程接收参数->sleep(50)->全局变量++->sleep(0)->输出参数和全局变量。

    要求:

    1. 子线程输出的线程序号不能重复

    2. 全局变量的输出必须是递增的

    下面画个简单的示意图:

    这个问题的考察点主要是:

    1.主线程创建子线程并传入一个指向变量地址的指针作参数,由于线程启动须要花费一定的时间,所以在子线程根据这个指针访问并保存数据前,主线程应等待子线程保存完毕后才能改动该参数并启动下一个线程。这涉及到主线程与子线程之间的同步

    2.子线程之间会互斥的改动和输出全局变量。要求全局变量的输出必须递增。这涉及到各子线程间的互斥

    #include <stdio.h>
    #include <process.h>
    #include <windows.h>
    //全局资源
    long g_nNum;
    //子线程个数
    const int THREAD_NUM = 10;
    
    unsigned int __stdcall Fun(void *param)
    {
    	int i = *(int *)param;
    	Sleep(50);
    	g_nNum++;
    	Sleep(0);
    	printf("线程编号为%d 全局资源为%d
    ", i, g_nNum);
    
    	return 0;
    }
    
    int main(void)
    {
    	g_nNum = 0;
    	HANDLE handle[THREAD_NUM];
    
    	int i = 0;
    	while (i < THREAD_NUM)
    	{
    		handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL);
    		i++;
    	}
    
    	//保证子线程全部运行结束并返回
    	WaitForMultipleObjects(THREAD_NUM, handle, true, INFINITE);
    
    	return 0;
    }

    执行结果:

    原因分析:

    正确的流程应该是:
    main线程创建thread1子线程,thread1把i的值读走,然后main线程执行i++。
    然后创建第二个线程,第二个线程再把更新后的i读走,然后main线程执行i++。
     
    现在错误的流程:
    main线程创建thread1子线程,然后thread1的创建需要一定的时间,main线程执行i++。
    之后main线程thread2子线程,同样thread2的创建也需要时间,main线程执行i++。
    然后thread1和thread2创建完成,分别可以执行了,然后读取i的值,但是这时i的值已经是3,
    不是当初main线程想传给它们的值。没有做好main线程和子线程的同步处理。
    

    通过执行的结果可以看出完全是混乱和不可预知的。

    接下来的几篇文章将运用Windows平台下的手段分析解决这个问题,方法包括关键段、事件、互斥量、信号量等方法。

  • 相关阅读:
    DSP Builder设计一个滤波器
    Modelsim 10.0 对Altera FFT IP 进行仿真
    FPGA内部计算小数
    TIOBE 2012年3月编程语言排行榜:JS超越Perl和Python
    转载 10个新鲜的Ajax相关的jQuery插件
    转载 使用HTML5、CSS3和jQuery增强网站用户体验
    转载 Java堆内存的10个要点
    累 腾讯笔试
    python 浮点数取整
    转载 一个页面重构工程师眼中的“用户体验”
  • 原文地址:https://www.cnblogs.com/stemon/p/4389771.html
Copyright © 2011-2022 走看看