- 互斥量:代表相互排斥或者能够给对象提供独占访问
- 死锁:指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
- 饥饿:进入死循环
解决方案有2个项目
- Windows窗口项目
pch.h
#ifndef PCH_H
#define PCH_H
// TODO: 添加要在此处预编译的标头
#pragma once
//#include "targetver.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <CommCtrl.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <stdio.h>
#pragma comment ( lib, "comctl32.lib" )
#pragma comment ( linker, "\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' \
version='6.0.0.0' processorArchitecture='*' \
publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif //PCH_H
PhilosophersDinner.cpp
// PhilosophersDinner.cpp : 主应用程序
#include "pch.h"
#pragma warning(disable:4302)
#define BUTTON_CLOSE 100
#define PHILOSOPHER_COUNT 5
#define WM_INVALIDATE WM_USER + 1
#define _CRT_SECURE_NO_DEPRECATE
#define _SCL_SECURE_NO_DEPRECATE
typedef struct _tagCOMMUNICATIONOBJECT
{
HWND hWnd;
bool bExitApplication;
int iPhilosopherArray[PHILOSOPHER_COUNT];
int PhilosopherCount;
} COMMUNICATIONOBJECT, *PCOMMUNICATIONOBJECT;
HWND InitInstance(HINSTANCE hInstance, int nCmdShow);
ATOM MyRegisterClass(HINSTANCE hInstance);
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam);
int PhilosopherPass(int iPhilosopher);
void FillEllipse(HWND hWnd, HDC hDC, int iLeft, int iTop, int
iRight, int iBottom, int iPass);
TCHAR* szTitle = (TCHAR*)TEXT("Philosophers Dinner Demo");
TCHAR* szWindowClass = (TCHAR*)TEXT("__PD_WND_CLASS__");
TCHAR* szSemaphoreName = (TCHAR*)TEXT("__PD_SEMAPHORE__");
TCHAR* szMappingName = (TCHAR*)TEXT("__SHARED_FILE_MAPPING__");
PCOMMUNICATIONOBJECT pCommObject = NULL;
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE
hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
HANDLE hMapping = CreateFileMapping((HANDLE)-1, NULL,
PAGE_READWRITE, 0, sizeof(COMMUNICATIONOBJECT), szMappingName);
if (!hMapping)
{
MessageBox(NULL, TEXT("Cannot open file mapping"),
TEXT("Error!"), MB_OK);
return 1;
}
pCommObject = (PCOMMUNICATIONOBJECT)MapViewOfFile(hMapping,
FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (!pCommObject)
{
MessageBox(NULL, TEXT("Cannot get access to file mapping! "),
TEXT("Error!"), MB_OK);
CloseHandle(hMapping);
return 1;
}
InitCommonControls();
MyRegisterClass(hInstance);
HWND hWnd = NULL;
if (!(hWnd = InitInstance(hInstance, nCmdShow)))
{
return FALSE;
}
pCommObject->bExitApplication = false;
pCommObject->hWnd = hWnd;
memset(pCommObject->iPhilosopherArray, 0,
sizeof(*pCommObject->iPhilosopherArray));
pCommObject->PhilosopherCount = PHILOSOPHER_COUNT;
HANDLE hSemaphore = CreateSemaphore(NULL,
int(PHILOSOPHER_COUNT / 2), int(PHILOSOPHER_COUNT / 2),
szSemaphoreName);
STARTUPINFO startupInfo[PHILOSOPHER_COUNT] =
{ { 0 }, { 0 }, { 0 }, { 0 }, { 0 } };
PROCESS_INFORMATION processInformation[PHILOSOPHER_COUNT] =
{ { 0 }, { 0 }, { 0 }, { 0 }, { 0 } };
HANDLE hProcesses[PHILOSOPHER_COUNT];
TCHAR szBuffer[8];
for (int iIndex = 0; iIndex < PHILOSOPHER_COUNT; iIndex++)
{
#ifndef UNICODE
wsprintf(szBuffer, L"%d", iIndex);
//#else
// sprintf((char*)szBuffer, "%d", iIndex);
#endif // !UNICODE
if (CreateProcess(TEXT("..\\Debug\\Philosopher.exe"),
szBuffer, NULL, NULL,
FALSE, 0, NULL, NULL, &startupInfo[iIndex],
&processInformation[iIndex]))
{
hProcesses[iIndex] = processInformation[iIndex].hProcess;
}
}
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
pCommObject->bExitApplication = true;
UnmapViewOfFile(pCommObject);
WaitForMultipleObjects(PHILOSOPHER_COUNT, hProcesses, TRUE, INFINITE);
for (int iIndex = 0; iIndex < PHILOSOPHER_COUNT; iIndex++)
{
CloseHandle(hProcesses[iIndex]);
}
CloseHandle(hSemaphore);
CloseHandle(hMapping);
return (int)msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wndEx;
wndEx.cbSize = sizeof(WNDCLASSEX);
wndEx.style = CS_HREDRAW | CS_VREDRAW;
wndEx.lpfnWndProc = WndProc;
wndEx.cbClsExtra = 0;
wndEx.cbWndExtra = 0;
wndEx.hInstance = hInstance;
wndEx.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wndEx.hCursor = LoadCursor(NULL, IDC_ARROW);
wndEx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndEx.lpszClassName = szWindowClass;
wndEx.lpszMenuName = NULL;
wndEx.hIconSm = LoadIcon(wndEx.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
return RegisterClassEx(&wndEx);
}
HWND InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPED
| WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 200, 200, 540, 590,
NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return NULL;
}
HFONT hFont = CreateFont(14, 0, 0, 0, FW_NORMAL, FALSE, FALSE,
FALSE, BALTIC_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH |
FF_MODERN, TEXT("Microsoft Sans Serif"));
HWND hButton = CreateWindow(TEXT("BUTTON"), TEXT("Close"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP, 410, 520, 100,
25, hWnd, (HMENU)BUTTON_CLOSE, hInstance, NULL);
SendMessage(hButton, WM_SETFONT, (WPARAM)hFont, TRUE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return hWnd;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case BUTTON_CLOSE:
{
DestroyWindow(hWnd);
break;
}
}
break;
}
case WM_INVALIDATE:
{
InvalidateRect(hWnd, NULL, TRUE);
break;
}
case WM_PAINT:
{
PAINTSTRUCT paintStruct;
HDC hDC = BeginPaint(hWnd, &paintStruct);
FillEllipse(hWnd, hDC, 210, 10, 310, 110,
PhilosopherPass(1));
FillEllipse(hWnd, hDC, 410, 170, 510, 270,
PhilosopherPass(2));
FillEllipse(hWnd, hDC, 335, 400, 435, 500,
PhilosopherPass(3));
FillEllipse(hWnd, hDC, 80, 400, 180, 500,
PhilosopherPass(4));
FillEllipse(hWnd, hDC, 10, 170, 110, 270,
PhilosopherPass(5));
EndPaint(hWnd, &paintStruct);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
default:
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
return 0;
}
int PhilosopherPass(int iPhilosopher)
{
return pCommObject->iPhilosopherArray[iPhilosopher - 1];
}
void FillEllipse(HWND hWnd, HDC hDC, int iLeft, int iTop, int
iRight, int iBottom, int iPass)
{
HBRUSH hBrush = NULL;
if (iPass)
{
hBrush = CreateSolidBrush(RGB(255, 0, 0));
}
else
{
hBrush = CreateSolidBrush(RGB(255, 255, 255));
}
HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
//Ellopse(hDC, iLeft, iTop, iRight, iBottom);
SelectObject(hDC, hOldBrush);
DeleteObject(hBrush);
}
- 控制台应用程序项目
pch.h
#ifndef PCH_H
#define PCH_H
// TODO: 添加要在此处预编译的标头
#pragma once
//#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#endif //PCH_H
Philosopher.cpp
// Philosopher.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <Windows.h>
#define EATING_TIME 1000
#define PHILOSOPHER_COUNT 5
#define WM_INVALIDATE WM_USER + 1
typedef struct _tagCOMMUNICATIONOBJECT
{
HWND hWnd;
bool bExitApplication;
int iPhilosopherArray[PHILOSOPHER_COUNT];
int PhilosopherCount;
} COMMUNICATIONOBJECT, *PCOMMUNICATIONOBJECT;
void Eat();
TCHAR* szSemaphoreName = (TCHAR*)TEXT("__PD_SEMAPHORE__");
TCHAR* szMappingName = (TCHAR*)TEXT("__SHARED_FILE_MAPPING__");
bool bExitApplication = false;
int _tmain(int argc, _TCHAR* argv[])
{
HWND hConsole = GetConsoleWindow();
ShowWindow(hConsole, SW_HIDE);
int iIndex = (int)_tcstol(argv[0], NULL, 10);
HANDLE hMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE,
szMappingName);
while (!bExitApplication)
{
HANDLE hSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE,
szSemaphoreName);
WaitForSingleObject(hSemaphore, INFINITE);
PCOMMUNICATIONOBJECT pCommObject = (PCOMMUNICATIONOBJECT)MapViewOfFile(hMapping,
FILE_MAP_ALL_ACCESS, 0, 0, sizeof(COMMUNICATIONOBJECT));
bExitApplication = pCommObject->bExitApplication;
if (!pCommObject->iPhilosopherArray[
(iIndex + pCommObject->PhilosopherCount - 1)
% pCommObject->PhilosopherCount]
&& !pCommObject->iPhilosopherArray[
(iIndex + 1) % pCommObject->PhilosopherCount])
{
pCommObject->iPhilosopherArray[iIndex] = 1;
Eat();
}
SendMessage(pCommObject->hWnd, WM_INVALIDATE, 0, 0);
pCommObject->iPhilosopherArray[iIndex] = 0;
UnmapViewOfFile(pCommObject);
ReleaseSemaphore(hSemaphore, 1, NULL);
CloseHandle(hSemaphore);
}
CloseHandle(hMapping);
return 0;
}
void Eat()
{
Sleep(EATING_TIME);
}
- 运行结果