线程同步之互斥对象(通俗易懂)

972 篇文章 329 订阅
32 篇文章 6 订阅

     先看售票系统的程序,看看多线程容易出什么问题:

#include <windows.h>
#include <iostream.h>

DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

int tickets = 100;

int main()
{
    HANDLE hThread1;
    HANDLE hThread2;

    hThread1 = CreateThread(NULL, 0, Fun1Proc, NULL, 0, NULL);
    hThread2 = CreateThread(NULL, 0, Fun2Proc, NULL, 0, NULL);

    CloseHandle(hThread1);
    CloseHandle(hThread2);
    Sleep(4000);

	return 0;
}

DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
    while(1)
    {    
        if(tickets > 0)
        {
            cout << "thread2 sell ticket : "<< tickets-- << endl;
        }
        else
		{
            break;   
		}
    }

	return 0;
}

DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
    while(1)
    {     
        if(tickets > 0)
        {
            cout << "thread1 sell ticket : " << tickets-- << endl;
        }
        else
		{
            break;
		} 
    }

	return 0;
}

      多运行几次,你会发现,程序不太正常,究竟是什么原因呢?线程不同步(同步的意思是协调,而非同时)。那么如何实现线程同步呢?我们可以利用互斥对象,程序如下:

#include <windows.h>
#include <iostream.h>

DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

int tickets = 100;
HANDLE hMutex = NULL;

int main()
{
	HANDLE hThread1;
	HANDLE hThread2;

	hMutex = CreateMutex(NULL, FALSE, NULL);

	hThread1 = CreateThread(NULL, 0, Fun1Proc, NULL, 0, NULL);
	hThread2 = CreateThread(NULL, 0, Fun2Proc, NULL, 0, NULL);

	CloseHandle(hThread1);
	CloseHandle(hThread2);
	
	Sleep(4000);
	CloseHandle(hMutex);

	return 0;
}

DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
	while(1)
	{
		WaitForSingleObject(hMutex, INFINITE);

		if(tickets > 0)
		{
			Sleep(1);
			cout << "thread1 sell ticket : " << tickets-- << endl;
		}
		else
		{
			break;
		}

		ReleaseMutex(hMutex);
	}
	
	return 0;
}

DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
	while(1)
	{
		WaitForSingleObject(hMutex, INFINITE);
		if(tickets > 0)
		{
			Sleep(1);
			cout << "thread2 sell ticket : "<< tickets-- << endl;
		}
		else
		{
			break;
		}

		ReleaseMutex(hMutex);
	}

	return 0;
}

        互斥对象是啥?互斥对象就像房子的唯一钥匙。我们来看看语句  WaitForSingleObject(hMutex, INFINITE); 当互斥对象处于无信号状态时, 表明有人在用这个钥匙,所以必须继续等待,当别人释放了这把钥匙的控制权后,互斥对象就会变得有信号,此时继续执行WaitForSingleObject(hMutex, INFINITE);语句后面的语句。

 

 

      注意弄清下面的几个概念(如果你在火车里面拉过屎,我相信你对互斥对象会有非常深刻的理解):

      互斥对象:唯一钥匙。

      互斥对象有信号(已通知状态):目前没有人用这个钥匙,故钥匙可用。

      互斥对象没有信号(未通知状态):目前有人在用这个钥匙,自己暂时不能用。

 

       好,现在来分析一下上面的程序:

       1. 主线程执行main函数,然后创建互斥对象和两个线程,主线程睡4秒钟的懒觉;

       2. 线程函数Fun1Proc获得执行,执行WaitForSingleObject(hMutex, INFINITE); 此时,互斥对象是有信号状态,相当于线程hThread1获得了互斥对象,操作系统立即将互斥对象变为无信号状态(让别的线程得不到该互斥对象,所以ticket变量安全了),程序继续向下执行;

       3. 线程hThread1睡0.001秒钟的懒觉,hThread2对应的函数Fun2Proc获得执行,其中的WaitForSingleObject(hMutex, INFINITE);得到调用,此时互斥对象处于无信号状态,不可用,因为线程hThread1已经独占了该互斥对象,所以Fun2Proc中的WaitForSingleObject函数就只能等呀等,等者等着,线程hThread1已经从0.001秒的美梦中清醒了,不再睡懒觉了,于是继续执行Sleep后面的语句,这样线程hThread1就卖出了第一张票。

       4. 接着,hThread1对应的函数Fun1Proc调用语句ReleaseMutex(hMutex); 释放了互斥对象,此时互斥立即不再为线程hThread1所独占,互斥对象立即变得有信号。这个时候,hThread2中的WaitForSingleObject终于盼到到互斥对象变成有信号,意思是hThread2终于获得了这个互斥对象,此时操作系统又将互斥对象设为无信号状态(让别的线程无法获得该互斥对象,所以ticket变量安全了)Fun2Proc继续执行,从而卖出了第二张票。

 

        接下来的分析就很俗套了。

 

 



 

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值