zoukankan      html  css  js  c++  java
  • windows多线程没那么难

    windows多线程没那么难

    作者:vpoet
    mail:vpoet_sir@163.com

    上一博文中我们引入了CreateThread()多线程编程一个简单的样例,其实我说windows
    多线程没那么难,那是为了安慰你,可是不要怕,困难时让人克服的。

    再大的困难也难不

    倒英雄的中国程序猿。

    以下我又要介绍一个多线程的问题:
    我们首先看一个Demo,经典的卖票问题,同一张牌不能卖出去两次:

    #include <windows.h>
    #include <stdio.h>
    
    static int number=20;
    
    DWORD WINAPI ThreadOne(LPVOID lpParameter)
    {
    	while(1)
    	{
    		if(number>0)
    		{
    			printf("窗体1售出第%d张票...
    ",number);
    			Sleep(1000);
    			number--;
    		}
    	}
    	return 0;
    }
    DWORD WINAPI ThreadTwo(LPVOID lpParameter)
    {
    	while(1)
    	{
    		if(number>0)
    		{
    			printf("窗体2售出第%d张票...
    ",number);
    			Sleep(1000);
    			number--;
    		}
    	}
    	return 0;
    }
    
    
    int main()
    {
    	HANDLE HOne,HTwo;
    	printf("***********************vpoet******************
    ");
    	HOne=CreateThread(NULL,0,ThreadOne,NULL,0,NULL);
    	printf("窗体1售票開始:
    ");
    	HTwo=CreateThread(NULL,0,ThreadTwo,NULL,0,NULL);
    	printf("窗体2售票開始:
    ");
    	CloseHandle(HOne);
    	CloseHandle(HTwo);
    	while(TRUE)
    	{
    		if(number==0)
    		{
    			printf("MainThread Over!
    ");
    			return 0;
    		}
    		else
    		{
    			continue;
    		}	
    	}
    
    	return 0;
    }
    执行结果:


    看到没,出现了同一张票卖两次的情况,这是绝对错误的。是违反能量守恒定律的。
    这是为什么呢。由于我们对全局变量操作两个线程在同一时候进行,假设在窗体1线程的number++
    之前,窗体2线程取出了number这时的number还并未自加,所以出现了同一张票
    卖两次的情况

    那么我们就要用线程同步的方法来控制,怎么控制呢,在windows下控制
    多线程同步一般有几种方法:临界区对象,事件对象和相互排斥对象以及锁
    以下主要介绍临界区对象进行线程同步:



    在win API中:


    该函数为初始化临界区函数,參数为临界区对象




    该函数等待指定的临界区对象的全部权,当获取指定的临界区对象的全部权之后该函数返回
    其參数为临界区对象指针



    该函数释放指定临界区对象的全部权,參数为临界区对象指针




    该函数为删除释放临界区对象资源






    那么接下来我们将用临界区对程序进行改写:
    #include <windows.h>
    #include <stdio.h>
    
    static int number=10;
    CRITICAL_SECTION Section;
    
    DWORD WINAPI ThreadOne(LPVOID lpParameter)
    {
    	while(1)
    	{
    		EnterCriticalSection(&Section);
    		if(number>0)
    		{
    			printf("窗体1售出第%d张票...
    ",number);
    			number--;
    			Sleep(1000);		
    		}
    		LeaveCriticalSection(&Section);
    	}
    	return 0;
    }
    DWORD WINAPI ThreadTwo(LPVOID lpParameter)
    {
    	while(1)
    	{
    		EnterCriticalSection(&Section);
    		if(number>0)
    		{
    			printf("窗体2售出第%d张票...
    ",number);
    			Sleep(1000);
    			number--;
    		}
    		LeaveCriticalSection(&Section);
    	}
    	return 0;
    }
    
    
    int main()
    {
    	HANDLE HOne,HTwo;
    	InitializeCriticalSection(&Section);
    	printf("***********************vpoet******************
    ");
    	HOne=CreateThread(NULL,0,ThreadOne,NULL,0,NULL);
    	printf("窗体1售票開始:
    ");
    	HTwo=CreateThread(NULL,0,ThreadTwo,NULL,0,NULL);
    	printf("窗体2售票開始:
    ");
    	CloseHandle(HOne);
    	CloseHandle(HTwo);
    	while(TRUE)
    	{
    		if(number==0)
    		{
    			printf("不好意思,票卖完了!
    ");
    			DeleteCriticalSection(&Section);
    			return 0;
    		}
    		else
    		{
    			continue;
    		}	
    	}
    
    	return 0;
    }
    执行结果例如以下:


    这下票卖对了吧。


    好了,Only stop here!
    以下的博文我将介绍其它几种线程同步的方法。
  • 相关阅读:
    在Docker中启动Nacos-Server
    maven配置阿里云公共仓库
    Centos7动态IP改静态后SSH很慢
    Vue+NodeJS的跨域请求Session不同
    一款非常简洁漂亮方便调用的jQuery前端分页
    springmvc后台接收List参数的几种办法
    net use命令详解(转)
    c#开发windows服务
    c# base64转字符串
    关于web api 验证
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6895012.html
Copyright © 2011-2022 走看看