<MFC笔记>多线程编程之线程的特性

本文通过一个火车售票系统的示例,展示了多线程环境下程序执行的随机性和不可预测性,并介绍了如何使用互斥对象解决线程同步问题。

一,线程的特性

1,随机性,系统在执行多线程程序时只保证线程是交替执行的,至于哪个线程先执行哪个线程后执行,则无法获得保证,需要书写专门的代码才可以保证执行的顺序。
2,多线程无法预测其行为,可能获得不同的结果。当然想要达到预期的效果需要xxx(暂时没有搞清楚)
3,task switches可能在任何时刻任何地点发生

4,线程对小的变化有高度的敏感



二,不可预测性和随机性

1,创建一个win32 console application工程,本工程创建了两个支线程,两个支线程执行模拟火车售票的程序!

输入代码如下:

输入代码如下:
#include "windows.h"
#include "iostream.h"
DWORD WINAPI FunProc1(LPVOID lpParameter);
DWORD WINAPI FunProc2(LPVOID lpParameter);
static int ticket=100;
void main()
{
 HANDLE hThread1;
 HANDLE hThread2;
 hThread1=CreateThread(NULL,0,FunProc1,NULL,0,NULL);
 hThread2=CreateThread(NULL,0,FunProc2,NULL,0,NULL);
 CloseHandle(hThread1);
 CloseHandle(hThread2);
 Sleep(4000);
}
DWORD WINAPI FunProc1(LPVOID lpParameter)
{
while(TRUE)
{
 if(ticket>0)
 {
 cout<<"ticket 1:"<<ticket--<<endl;
 }
 else
 break;
}
return 0;
}
DWORD WINAPI FunProc2(LPVOID lpParameter)
{
while(TRUE)
{
 if(ticket>0)
 {
 cout<<"ticket 2:"<<ticket--<<endl;
 }
 else
 break;
}
return 0;
}

2,结果(以下均为未更改代码的前提下多次运行的结果)
图未接完,只展示前面的部分数据!

三,解决上诉现象

(利用互斥对象实现线程同步)

1,在上诉代码的基础上添加代码如下:红色为新添加的代码!

#include "windows.h"
#include "iostream.h"
DWORD WINAPI FunProc1(LPVOID lpParameter);
DWORD WINAPI FunProc2(LPVOID lpParameter);
static int ticket=100;
HANDLE hMutex;    //保存互斥对象
void main()
{
 HANDLE hThread1;
 HANDLE hThread2;
 hMutex=CreateMutex(NULL,FALSE,NULL);    //创建互斥对象,互斥对象可比喻成钥匙</span>
 hThread1=CreateThread(NULL,0,FunProc1,NULL,0,NULL);
 hThread2=CreateThread(NULL,0,FunProc2,NULL,0,NULL);
 CloseHandle(hThread1);
 CloseHandle(hThread2);
 Sleep(4000);
}
DWORD WINAPI FunProc1(LPVOID lpParameter)
{
while(TRUE)
{WaitForSingleObject(hMutex,INFINITE);            //申请“钥匙”(即互斥对象)的所有权,一直等待
 if(ticket>0)
 {
  Sleep(1);   //让线程1暂停1毫秒</span>
 cout<<"ticket 1:"<<ticket--<<endl;
 }
 else
 break;
  ReleaseMutex(hMutex);            //执行完后,释放所有权
}
return 0;
}
DWORD WINAPI FunProc2(LPVOID lpParameter)
{
while(TRUE)
{
 WaitForSingleObject(hMutex,INFINITE);</span>
 if(ticket>0)
 {Sleep(1);
 cout<<"ticket 2:"<<ticket--<<endl;
 }
 else
 break;
  ReleaseMutex(hMutex);
}
return 0;
}


2,运行结果(多次运行的如果都是如此)


3,运行结果分析
(1)CreateMutex(NULL,FALSE,NULL)各参数的意义(顺序解释):默认安全性,创建该互斥对象的线程不获得这个互斥对象,创建一个匿名的互斥对象!一定要记住:谁拥有互斥对象,谁就必须释放!如果设置为TRUE则,必须在主程序释放互斥对象。
(2)WaitForSingleObject(hMutex,INFINITE):互斥对象,无限等待线程来请求互斥对象的所有权。当运行到这一句时线程1和线程2就会一直等待,除非所等待的互斥对象hMetux处于有信号状态(即没有被“别人”拿走了钥匙,或者说互斥对象没有被申请!)
(3)程序的执行过程:当第一个线程运行时,进入while循环,申请“钥匙”(此时钥匙没有被拿走),所以线程1得到了互斥对象(操作系统随后将互斥对象的线程id改为线程1的id),线程1便继续执行下去,调用sleep,暂停一小会,于是系统会选择线程2开始执行,该线程执行过程也一样!!!但是因为互斥对象已经被线程1所拥有,处于无信号状态所以线程2一直处于等待状态!线程1暂停结束,开始执行任务,最后释放所有权!线程2申请得到互斥对象,开始执行任务,然后释放......................

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值