zoukankan      html  css  js  c++  java
  • 秒杀多线程第四篇 一个经典的多线程同步问题

    上一篇《秒杀多线程第三篇原子操作 Interlocked系列函数》中介绍了原子操作在多进程中的作用,如今来个复杂点的。这个问题涉及到线程的同步和相互排斥,是一道很有代表性的多线程同步问题,假设能将这个问题搞清楚,那么对多线程同步也就打下了良好的基础。

     

    程序描写叙述:

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

    要求:

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

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

    以下画了个简单的示意图:

    分析下这个问题的考察点,主要考察点有二个:

    1.主线程创建子线程并传入一个指向变量地址的指针作參数,因为线程启动需要花费一定的时间,所以在子线程依据这个指针訪问并保存数据前,主线程应等待子线程保存完成后才干修改该參数并启动下一个线程。这涉及到主线程与子线程之间的同步

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

     

    以下列出这个程序的基本框架,能够在此代码基础上进行修改和验证。

    //经典线程同步相互排斥问题
    #include <stdio.h>
    #include <process.h>
    #include <windows.h>
    
    long g_nNum; //全局资源
    unsigned int __stdcall Fun(void *pPM); //线程函数
    const int THREAD_NUM = 10; //子线程个数
    
    int main()
    {
    	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++;//等子线程接收到參数时主线程可能改变了这个i的值
    	}
    	//保证子线程已所有执行结束
    	WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);  
    	return 0;
    }
    
    unsigned int __stdcall Fun(void *pPM)
    {
    //因为创建线程是要一定的开销的,所以新线程并不能第一时间运行到这来
    	int nThreadNum = *(int *)pPM; //子线程获取參数
    	Sleep(50);//some work should to do
    	g_nNum++;  //处理全局资源
    	Sleep(0);//some work should to do
    	printf("线程编号为%d  全局资源值为%d
    ", nThreadNum, g_nNum);
    	return 0;
    }

    执行结果能够參考下列图示,强烈建议读者亲自试一试。

    1

    2

    3

    能够看出,执行结果全然是混乱和不可预知的。本系列将会运用Windows平台下各种手段包含关键段,事件,相互排斥量,信号量等等来解决问题并作一份全面的总结,敬请关注。

     

    秒杀多线程第五篇 经典线程同步 关键段CS》已经公布,欢迎參阅。

    秒杀多线程第六篇 经典线程同步 事件Event》已经公布,欢迎參阅。

    秒杀多线程第七篇 经典线程同步 相互排斥量Mutex已经公布,欢迎參阅。

    秒杀多线程第八篇 经典线程同步 信号量Semaphore已经公布,欢迎參阅。 

     

     

    转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/7442333

     

  • 相关阅读:
    HashMap按键排序和按值排序
    LeetCode 91. Decode Ways
    LeetCode 459. Repeated Substring Pattern
    JVM
    LeetCode 385. Mini Parse
    LeetCode 319. Bulb Switcher
    LeetCode 343. Integer Break
    LeetCode 397. Integer Replacement
    LeetCode 3. Longest Substring Without Repeating Characters
    linux-网络数据包抓取-tcpdump
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3923925.html
Copyright © 2011-2022 走看看