Sleeping Barber Window版本实现

来源:互联网 发布:网络商品交易改革 编辑:程序博客网 时间:2024/05/16 10:29

介绍:

题目来自于开源力量(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;}

运行结果:

客人未上门:


收到关门指令:


0 0