Sleeping Barber Window版本实现

介绍:

题目来自于开源力量(www.osforce.cn) C语言进阶课程

 具体如下:

一间理发店有3位理发师,理发店有沙发,最多坐10人。

3个理发师是三个线程,没有客人时,理发师睡觉。客人上门时,理发师醒过来服务客人。如果理发师都在忙,客人则坐到沙发上等待,如果沙发满了,客人直接离开。

收到关门信号的时候,沙发上的客人直接离开,对于服务到一半的客人,理发师要帮他们剪完头发。

总共两个进程,一个是理发店的,另一个用于发送客人上门和关门命令。


负责发送命令的进程:

界面如下:


事件初始化代码:

//事件名称
const wchar_t szCustomerComeEvent[] = L"szCustomerComeEvent";
const wchar_t szCloseShopEvent[] = L"szCloseShopEvent";

CbarberShopDlg::CbarberShopDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CbarberShopDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

    //在对话框类的构造函数中创建事件
    m_customerComeEvent = ::CreateEvent(NULL,TRUE,FALSE,szCustomerComeEvent);
    m_closeShopEvent = ::CreateEvent(NULL,TRUE,FALSE,szCloseShopEvent);
}

事件触发代码:

//客人上门
void CbarberShopDlg::OnBnClickedCustomerComeButton()
{
    ::SetEvent(m_customerComeEvent);
    ::ResetEvent(m_closeShopEvent);
}

//理发店关门
void CbarberShopDlg::OnBnClickedCloseButton()
{
    ::SetEvent(m_closeShopEvent);
    ::ResetEvent(m_customerComeEvent);
}

对话框结束清理事件:

CbarberShopDlg::~CbarberShopDlg()
{
    //关闭事件
    CloseHandle(m_customerComeEvent);
    CloseHandle(m_closeShopEvent);
}

理发师实现进程:

//理发师的数量
const int BARBER_COUNT = 3;

//沙发的容量
const int SOFA_CONTAIN_COUNT = 10;

//客人上门的事件名称
const wchar_t szCustomerComeEvent[] = L"szCustomerComeEvent";

//理发店关门的事件名称
const wchar_t szCloseShopEvent[] = L"szCloseShopEvent";

//信号量的名称
const wchar_t szSemaphoreName[] = L"szSemaphoreName";

//沙发
int SOFA[SOFA_CONTAIN_COUNT];

//客人上门事件的句柄
HANDLE g_customerComeEvent = 0;

//理发店关门事件的句柄
HANDLE g_closeShopEvent = 0;

//信号量句柄
HANDLE g_semphore = 0;

//保护沙发的临界区变量
CRITICAL_SECTION g_sofaSection;

DWORD WINAPI BarberProc(  LPVOID lpParameter)
{
    //获取线程的id
    int barberId = *((int*)lpParameter);
    //等待客人上门,延时0
    if(WAIT_TIMEOUT==::WaitForSingleObject(g_customerComeEvent,0))
    {
        //客人没有上门,打印 理发师正在睡觉
        printf("barber %d is sleeping \n",barberId);
        //等待客人上门,永久
        ::WaitForSingleObject(g_customerComeEvent,INFINITE);
    }

    HANDLE handles[2] = {g_closeShopEvent,g_semphore};
    while(true)
    {
        //等待关门事件或者客人坐到沙发上
        DWORD result = ::WaitForMultipleObjects(2,handles,FALSE,INFINITE);
        //信号量
        if((WAIT_OBJECT_0+1)==result)
        {
            //从沙发里面取出一个客户
            ::EnterCriticalSection(&g_sofaSection);
            int customerId = SOFA[0];
            assert(customerId>0);
            memcpy(SOFA,SOFA+1,(SOFA_CONTAIN_COUNT-1)*sizeof(SOFA[0]));
            SOFA[SOFA_CONTAIN_COUNT-1]=0;
            ::LeaveCriticalSection(&g_sofaSection);

            printf("barber %d is working on customer %d \n",barberId,customerId);
            Sleep(4000);
        }
        //关门信号
        else if((WAIT_OBJECT_0)==result)
        {
            printf("barber %d is after work\n",barberId);
            return 0;
        }
        else
        {
            assert(false);
            return 0;
        }
    }
    return 0;
}



int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    //初始化沙发
    memset(SOFA,0,sizeof(SOFA));
    //初始化临界区
    ::InitializeCriticalSection(&g_sofaSection);

    //创建信号量
    g_semphore=::CreateSemaphore(NULL,0,SOFA_CONTAIN_COUNT,szSemaphoreName);
    if(0==g_semphore)
    {
        goto EXIT;
    }

    //创建事件
    g_customerComeEvent = ::CreateEvent(NULL,TRUE,FALSE,szCustomerComeEvent);
    if(0==g_customerComeEvent)
    {
        goto EXIT;
    }
    g_closeShopEvent = ::CreateEvent(NULL,TRUE,FALSE,szCloseShopEvent);
    if(0==g_closeShopEvent)
    {
        goto EXIT;
    }

    //创建理发师线程
    HANDLE barberThread[BARBER_COUNT] ={0};
    int barberId[BARBER_COUNT]={0};
    DWORD dword;
    for(int i=0;i<BARBER_COUNT;++i)
    {
        barberId[i] = i+1;
        barberThread[i] = ::CreateThread(NULL,0,BarberProc,&barberId[i],0,&dword);
        if(0==barberThread[i])
        {
            goto EXIT;
        }
    }

    HANDLE h[2]={g_closeShopEvent,g_customerComeEvent};
    int customerId = 1;
    while(true)
    {
        DWORD result = ::WaitForMultipleObjects(2,h,FALSE,INFINITE);

        //客人上门
        if((WAIT_OBJECT_0+1)==result)
        {
            //检查沙发是否已满
            if(0!=SOFA[SOFA_CONTAIN_COUNT-1])
            {
                //满 让客人自己离开
                printf("sofa is full \n");
                printf("customer %d is leaving \n",customerId);
            }
            else
            {
                //未满 将客人放入沙发
                ::EnterCriticalSection(&g_sofaSection);
                for(int i=0;i<SOFA_CONTAIN_COUNT;++i)
                {
                    if(0==SOFA[i])
                    {
                        SOFA[i] = customerId;
                        printf("customer %d is sitting on the sofa \n",customerId);
                        break;
                    }
                }
                ::LeaveCriticalSection(&g_sofaSection);
                long previousNum = 0;
                //
                ::ReleaseSemaphore(g_semphore,1,&previousNum);
            }
            Sleep(1000);

            customerId++; 
        }
        //关门
        else if((WAIT_OBJECT_0)==result)
        {
            printf("the shop is going to close \n");
            ::EnterCriticalSection(&g_sofaSection);
            for(int i=0;i<SOFA_CONTAIN_COUNT;++i)
            {
                if(0!=SOFA[i])
                {
                    printf("customer %d is leaving \n",SOFA[i]);
                    SOFA[i] = 0;
                }
            }
            ::LeaveCriticalSection(&g_sofaSection);

            //等待理发师线程的结束
            ::WaitForMultipleObjects(BARBER_COUNT,barberThread,TRUE,INFINITE);
            //跳出循环
            break;
        }
        else
        {
            assert(false);
            goto EXIT;
        }

    }        

    //善后及异常处理:
EXIT:
    //删除临界区
    DeleteCriticalSection(&g_sofaSection);

    //关闭事件
    CloseHandle(g_customerComeEvent);
    g_customerComeEvent = 0;
    CloseHandle(g_closeShopEvent);
    g_closeShopEvent = 0;

    //关闭信号量
    CloseHandle(g_semphore);
    g_semphore = 0;

    //关闭线程
    for(int i=0;i<BARBER_COUNT;++i)
    {
        CloseHandle(barberThread[i]);
        barberThread[i] = 0;
    }
    return 0;
}

运行结果:

客人未上门:


收到关门指令:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值