哲学家就餐问题

一、问题描述:
有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子每个哲学家的行为是思考,感到饥饿,然后吃通心粉.为了吃通心粉,每个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边去取筷子。
二、防止死锁发生的分配方式:

仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子。这样要么一次占有两只筷子(所有线程需要的资源)进行下一步的吃通心粉,然后释放所有的资源;要么不占用资源,这样就不可能产生死锁了。

三、产生死锁的分配方式:

当筷子(资源)可用时,先分配左边的筷子,等待一会后再分配右边的筷子,由于这个过程中,左边的筷子一直没有释放,就有可能产生死锁了。

四、程序运行说明

程序运行过程中会弹出一个MessageBox提示操作者操作:

1.第一个对话框用于选择运行模式

   a.选择yes 表示采用的是运行的防止死锁的方式,这样的话整个程序可以一直运行下去,不会产生死锁。

   b.选择no 表示运行产生死锁的方式会弹出第二个对话框。

2.第二个对话框用于选择运行时,线程运行的时间

   a. 选择 res 线程时间比较短,很快就可以死锁

   b.选择no 线程时间跟选择yes 时候的时间差不多,产生死锁的时间稍微长一点

 

五、关于哲学家就餐问题的程序代码分析:

A. Dining.c

变量说明:

HINSTANCE             hInst

应用实例句柄

HWND         hWndMain

主窗口句柄

HBITMAP        hbmpOffscreen

位图句柄

BOOL        bWaitMultiple

用于选择等待的方式(要么死锁,要么一直循环运行)

BOOL bFastFood;

用于选择进程等待的时间

extern int gDinerState[]

用于表示哲学家的状态(外部接口) 

extern int gChopstickState[]

用于表示筷子的状态

extern HANDLE gchopStick[PHILOSOPHERS]

筷子的数组

 

函数说明:

 

 

 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

处理消息函数:

    根据进程调度的消息的不同处理不同的消息包括:关闭窗口,销毁资源,画窗口,和重画窗口等

 

BOOL CreateOffscreen()

获得当前窗口的一个位图句柄

void RenderOffscreen(HDC hDestDC)

通过位图句柄画演示的界面

  1.先画桌子,再画筷子,再画盘子,

2.再画哲学家:

哲学家用圆表示,根据哲学家的状态选择画笔(为resting 状态时为绿色圆圈,为等待或者,就餐时为红色圆圈)

3.最后画哲学家的手:

判断的依据是若筷子的编号和哲学家的编号一致,那么认为这根筷子属于这个哲学家(筷子资源空闲)那么可以画手表示哲学家获得了这个筷子。(获得资源)

 

BOOL InitApplication(HINSTANCE hInstance)

初始化应用窗口

 

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)

初始化主窗口

弹出选择对话框进行模式选择,并启动进程

 

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

            LPSTR lpCmdLine, int nCmdShow)    

 

调用前面的函数并对进线程消息进行处理

 

 

BMutex.c

变量说明:

extern HWND hWndMain

Dining.c中定义是这个文件的外部接口

extern BOOL bWaitMultiple

 

Dining.c中定义是这个文件的外部接口

extern BOOL bFastFood

Dining.c中定义是这个文件的外部接口

int gDinerState[PHILOSOPHERS]

哲学家状态数组

int gChopstickState[PHILOSOPHERS]

 

筷子状态数组

HANDLE gchopStick[PHILOSOPHERS]

筷子状态数组

 

 

                              

函数说明:

1.  DWORD WINAPI PhilosopherThread(LPVOID pVoid)

哲学家进程:

用于分配给哲学家筷子(资源)通过开始运行时候的对话框的选择来控制资源的分配方式:两中分配方式见二、三所述。通过随机产生的时间来控制线程的运行,

每个哲学家的状态都是resting waiting eating,一直循环。

2int Diner(void)

用于建立互斥的信号对象(筷子)和启动哲学家进程

 

 

/*

 * Dining.c

 *

 * Sample code for "Multithreading Applications in Win32"

 * This sample is discussed in Chapter 4.

 *

 * Graphically demonstrates the problem of the

 * dining philosophers.

 */

 

#define WIN32_LEAN_AND_MEAN

#include <stdio.h>

#include <stdlib.h>

#include <windows.h>

#include <windowsx.h>

#include <string.h>

#include <math.h>

#include "dining.h"

 

HINSTANCE       hInst;                  // Application Instance Handle

HWND   hWndMain;               // Main Window Handle                             

HBITMAP hbmpOffscreen;

 

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

void RenderOffscreen(HDC hDestDC);

 

BOOL bWaitMultiple;

BOOL bFastFood;

 

extern int gDinerState[];

extern int gChopstickState[];

extern HANDLE gchopStick[PHILOSOPHERS]; // 1 chopstick between each philopher and his neighbor

 

/********************************************************************/

/*      ROUTINE:        WndProc                                                                 */

/*                                                                                                               */

/*      PURPOSE:        Processes messages                                                                */

/********************************************************************/

 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message,

        WPARAM wParam, LPARAM lParam)

{

        PAINTSTRUCT ps;

        HDC hdc;

 

        switch (message)

        {

                case WM_COMMAND:

                        switch (wParam)

                        {

                        case CM_EXIT:

                                PostMessage(hWndMain, WM_CLOSE, 0, 0L);

                                break; 

                        }

                        break;

 

                case WM_FORCE_REPAINT:

                        {

                                MSG msg;

 

                                InvalidateRect(hWndMain, NULL, TRUE);

                                while (PeekMessage(&msg, hWndMain, WM_FORCE_REPAINT,WM_FORCE_REPAINT,TRUE))

                                        ;

                        }

                        break;

 

                case WM_PAINT:

                       

                        hdc = BeginPaint(hWndMain, &ps);

 

                        RenderOffscreen(hdc);

                       

                        EndPaint(hWndMain, &ps);

                        break;

 

                case WM_CLOSE:

                        return DefWindowProc(hWndMain, message, wParam, lParam);

 

                case WM_DESTROY:

                        PostQuitMessage(0);

                        break;

 

                default:

                        return DefWindowProc(hWnd, message, wParam, lParam);

}

        return (0);

}

 

BOOL CreateOffscreen()

{

        HWND hwndScreen = GetDesktopWindow();

        HDC hdc = GetDC(hwndScreen);

 

        int     nWidth  = GetSystemMetrics( SM_CXSCREEN );

        int     nHeight = GetSystemMetrics( SM_CYSCREEN );

 

        hbmpOffscreen = CreateCompatibleBitmap( hdc, nWidth, nHeight );

 

        ReleaseDC(hwndScreen, hdc);

 

        if ( !hbmpOffscreen )

                return FALSE;

        else

                return TRUE;

}

 

void RenderOffscreen(HDC hDestDC)

{

        HDC hdc                         = hDestDC; // CreateCompatibleDC(hWndMain);

        int err=GetLastError();

        HBITMAP hOldBitmap      = SelectObject(hdc, hbmpOffscreen);

        RECT rect;

        HPEN hPen;

        double dx, dy, px, py,  AngRad, dDeltaAng;

        int pos, p1;

        long CenterX, CenterY;

 

        hPen = SelectObject(hdc, CreatePen(PS_SOLID, 3, 0L));

 

        GetClientRect(hWndMain, &rect);

 

        /* Draw the table */

        CenterX = (rect.right - rect.left)/2;

        CenterY = (rect.bottom - rect.top)/2;

        Ellipse(hdc, CenterX - 100, CenterY - 100, CenterX + 100, CenterY + 100);

 

        /* Draw the chopsticks */

        dDeltaAng = 360 / PHILOSOPHERS;    //筷子间的角度差

        for (pos = 0; pos < PHILOSOPHERS; pos++)        //FIXIT

        {

                /* Draw the chopsticks */

                AngRad = (pos * dDeltaAng)/57.29577951;  //转化为弧度

                dx = CenterX + (sin(AngRad)*60);

                dy = CenterY - (cos(AngRad)*60);

                MoveToEx(hdc, (int)dx, (int)dy, NULL);

                dx = CenterX + (sin(AngRad)*85);

                dy = CenterY - (cos(AngRad)*85);

                LineTo(hdc, (int)dx, (int)dy);

 

                //Draw the plate

                AngRad = ((pos * dDeltaAng+dDeltaAng / 2))/57.29577951;  //转化为弧度

                dx = CenterX + (sin(AngRad) * 72);

                dy = CenterY - (cos(AngRad) * 72);

                Ellipse(hdc, (int)dx-12, (int)dy-12, (int)dx+12, (int)dy+12);

        }

 

        /* delete the black pen */

        DeleteObject(SelectObject(hdc, hPen));

 

        /* Draw the philosophers */

        for(pos = 0; pos < PHILOSOPHERS; pos++)

        {

                /* select a pen for each philosopher */

                switch (gDinerState[pos])

                {

                case RESTING:

                        hPen = SelectObject(hdc, CreatePen(PS_SOLID, 3, RGB(0, 255, 0)));

                        break;

 

                case WAITING:

                case EATING:

                        hPen = SelectObject(hdc, CreatePen(PS_SOLID, 3, RGB(255, 0, 0)));

                        break;

 

                default:

                        hPen = SelectObject(hdc, CreatePen(PS_SOLID, 3, 0L));

                }

 

                AngRad = ((pos * dDeltaAng) + dDeltaAng / 2)/57.29577951;

                px = CenterX + (sin(AngRad)*150);

                py = CenterY - (cos(AngRad)*150);

 

                /* Draw the Philosopher */

                Ellipse(hdc, (int)px-25, (int)py-25, (int)px+25, (int)py+25);

 

                //Draw the left arm

                if (gChopstickState[pos] == pos)

                {

                        MoveToEx(hdc, (int)px, (int)py, NULL);

                        AngRad = (pos * dDeltaAng)/57.29577951; //转化为弧度

                        dx = CenterX + (sin(AngRad)*85);

                        dy = CenterY - (cos(AngRad)*85);

                        LineTo(hdc, (int)dx, (int)dy);

                }

 

                //Draw the right arm

                p1 = pos + 1;

                if (p1 == PHILOSOPHERS)

                        p1 = 0;

                if (gChopstickState[p1] == pos)

                {

                        MoveToEx(hdc, (int)px, (int)py, NULL);

                        AngRad = (p1 * dDeltaAng)/57.29577951;

                        dx = CenterX + (sin(AngRad)*85);

                        dy = CenterY - (cos(AngRad)*85);

                        LineTo(hdc, (int)dx, (int)dy);

                }

 

                /* Delete the pen */

                DeleteObject(SelectObject(hdc, hPen));                 

        }       //for pos

 

        BitBlt( hDestDC,

                                rect.left,

                                rect.top,

                                rect.right - rect.left,

                                rect.bottom-rect.top,

                                hdc,

                                rect.left,

                                rect.top,

                                SRCCOPY

                        );

        GetLastError();

 

        SelectObject(hdc, hOldBitmap);

 

//      DeleteDC(hWndMain, hdc);

}

 

/********************************************************************/

/*      ROUTINE:        InitApplication                                                         */

/*                                                                                                              */

/*      PURPOSE:        Initialize the application                                              */

/********************************************************************/

 

BOOL InitApplication(HINSTANCE hInstance)

{

        WNDCLASS  wc;

 

        wc.style = CS_HREDRAW | CS_VREDRAW;

        wc.lpfnWndProc = WndProc;

        wc.cbClsExtra = 0;

        wc.cbWndExtra = 0;

        wc.hInstance = hInstance;

        wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

        wc.hCursor = LoadCursor(NULL, IDC_ARROW);

        wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

        wc.lpszMenuName =  "din";

        wc.lpszClassName = "dinWClass";

 

        RegisterClass(&wc);

 

        return TRUE;

}

 

 

/********************************************************************/

/* ROUTINE:  InitInstance                                                                       */

/*                                                                                                              */

/* PURPOSE:  Saves instance handle and creates main window              */

/********************************************************************/

 

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)

{

        int ret;

 

        hInst = hInstance;

 

        hWndMain = CreateWindow(

                "dinWClass",

                "Dining Philosopher",

                WS_OVERLAPPEDWINDOW,

                CW_USEDEFAULT,

                CW_USEDEFAULT,

                450,

                450,

                NULL, NULL, hInstance, NULL );

 

        if (!hWndMain)

                return FALSE;

 

        ShowWindow(hWndMain, nCmdShow);

        UpdateWindow(hWndMain);

 

        if (!CreateOffscreen())

                PostQuitMessage(1);

 

        ret = MessageBox(hWndMain, "你期望使用防死锁运行模式吗?/n/n"

                "如果选择Yes, 程序将正常运行./n"

                "如果选择No, 程序会进入死锁./n",

                "Wait Mode", MB_YESNO);

        if (ret == IDYES)

                bWaitMultiple = TRUE;

        else

        {

                bWaitMultiple = FALSE;

 

                ret = MessageBox(hWndMain, "你期望快速进入死锁吗?/n/n"

                        "如果选择Yes, 将更快进入死锁./n",

                        "Wait Mode", MB_YESNO);

                if (ret == IDYES)

                        bFastFood = TRUE;

                else

                        bFastFood = FALSE;

        }

 

        // Start the threads

        Diner();

 

        return TRUE;

}

 

/********************************************************************/

/* FUNCTION: WinMain                                                                            */

/*                                                                                                              */

/* PURPOSE: Calls initialization function, processes message loop       */

/********************************************************************/

 

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

        LPSTR lpCmdLine, int nCmdShow)

{

        MSG msg;

        int i;

 

        if (!hPrevInstance)

                if (!InitApplication(hInstance))

                        return (FALSE);

 

        if (!InitInstance(hInstance, nCmdShow))

                return (FALSE);

 

        while (GetMessage(&msg, NULL, 0, 0))

        {

                TranslateMessage(&msg);

                DispatchMessage(&msg);

        }

        // Clear the table

        for (i = 0; i < PHILOSOPHERS; i++)

                CloseHandle(gchopStick[i]); //关闭互斥体句柄

        return (msg.wParam);

}

 

 

《内存管理》实验指导书

【实验内容】

设计一个虚拟存储区和内存工作区,并使用下列算法计算访问命中率。

(1)       进先出的算法(FIFO

(2)       最近最少使用的算法(LRU

(3)       最佳淘汰算法(OPT)

       命中率=(1-页面失效次数)/页地址流长度

【实验要求】

1、  理解FIFO,LRU算法原理,理解参考程序的原理和实现思路。

2、  完成程序的设计,重点完成FIFO,LRU算法

3、  分析运算结果,在分配不同的物理块情况下,各算法的缺页情况有什么规律?

4、  完成OPT算法

【程序设计指导】

       本实验的程序设计基本上按照实验内容进行。即首先用srand()rand()函数定义和产生指令序列,然后将指令序列变换成相应的页地址流,并针对不同的算法计算出相应的命中率。实验中我们产生320条指令,每个虚拟页存放10条指令。进程分配的物理块从4变化到32

【重要变量、结构和函数的建议】

(1)页面类型

 typedef struct

{

int pn;

int pfn;

int counter;

int time

} pl-type;

其中pn 为页号,pfn为面号, counter为一个周期内访问该页面的次数, time为访问时间。

(2) 页面控制结构

pfc_struct

{

       int pn,pfn;

       struct pfc_struct *next;

}

typedef   struct pfc_struct pfc_type;

pfc_type  pfc_struct[total_vp], *freepf_head, *busypf_head;

pfc_type  *busypf_tail;

   其中:

pfc[total_vp]定义用户进程虚页控制结构。

*freepf_head为空页面头的指针。

*busypf_head为忙页面头的指针。

*busypf_tail为忙页面尾的指针。

3)函数定义

       void initialize( ):初始化函数,给每个相关的页面赋值。

       void FIFO( ):计算使用FIFO算法时的命中率。

       void LRU( ):计算使用LRU算法时的命中率。

4)变量定义

      int a[total_instruction]: 指令流数据组。

      int page[total_instruction]: 每条指令所属的页号。

      int offset[total_instruction]: 每页装入10条指令后取模运算页号偏移值。

      int total_pf: 用户进程的内存页面数。

      int disaffect: 页面失效次数。

【参考资料】

// Store.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"

#include <windows.h>

#include <stdio.h>

#include <process.h>

 

#define TRUE 1

#define FALSE 0

#define INVALID -1

#define NULL 0

 

#define NUMBER_OF_INSTRUCTION 320  //指令流的指令条数

#define NUMBER_OF_VP 32            //进程的虚页页数

 

//#define LINEAR_ADDRESS

      

typedef struct

{

    int no_of_vp;            //虚拟页号

    int no_of_pp;            //物理页号

    int counter_in_period;   //一周期内访问的次数

    int time;               //访问时间

}vp_struct;    //页面类型

 

vp_struct vp_array[NUMBER_OF_VP];        //页面结构数组

 

 

struct pp_struct           //物理页面结构

{

    int no_of_vp;

    int no_of_pp;

    struct pp_struct *next;

};

 

typedef struct pp_struct pp_type;

pp_type pp_control[NUMBER_OF_VP],*free_pp_head,*busy_pp_head,*busy_pp_tail;

 

int counter_page_default;

int address_of_instruction[NUMBER_OF_INSTRUCTION];

 

int page_of_instruction[NUMBER_OF_INSTRUCTION],offset_of_instruction[NUMBER_OF_INSTRUCTION];

 

int MAXINT=((1<<30)-1)*2+1; //2^31-1 2147483647

      

void initialize(int);

 

void FIFO(int);  //先进先出

void LRU(int);   //最近最久未使用页面淘汰算法(least recently used

 

int main()

{

        int S,i;

        srand( (int)getpid() );

    S=(int)rand() % 320;

#ifndef LINEAR_ADDRESS   

    for(i=0;i<NUMBER_OF_INSTRUCTION;i+=1)  /*产生指令队列*/

        {

                address_of_instruction[i]=S;                               /*任选一指令访问点*/

                address_of_instruction[i+1]=address_of_instruction[i]+1;   /*顺序执行一条指令*/

                address_of_instruction[i+2]=(int)rand()%320;              /*执行前地址指令m'*/

                address_of_instruction[i+3]=address_of_instruction[i+2]+1; /*执行后地址指令*/

                S=(int)rand()%320;

        }

#else

    for(i=0;i<NUMBER_OF_INSTRUCTION;i+=1)  /*产生指令队列*/

        {

                address_of_instruction[i]=i;

        }

#endif

        for(i=0;i<NUMBER_OF_INSTRUCTION;i++)               /*将指令序列变换成页地址流*/

        {      

                page_of_instruction[i]=address_of_instruction[i]/10;

                offset_of_instruction[i]=address_of_instruction[i]%10;

        }

       

        for(i=4;i<=32;i++)                        /*用户内存工作区从个页面到个页面*/

        {

                printf("%2d 物理块:",i);

                FIFO(i);

                LRU(i);

                printf("/n");

        }

       

        return 0;

}

 

void FIFO(int total_pf)

{

    int i,j;

    pp_type *p,*t;

    initialize(total_pf);

    busy_pp_head=busy_pp_tail=NULL;

    for(i=0;i<NUMBER_OF_INSTRUCTION;i++)

    {

    if(vp_array[page_of_instruction[i]].no_of_pp==INVALID)

    {

        counter_page_default+=1;

        if(free_pp_head==NULL)

        {

                        p=busy_pp_head->next;

                        vp_array[busy_pp_head->no_of_vp].no_of_pp=INVALID;

                        free_pp_head=busy_pp_head;

                        free_pp_head->next=NULL;

                        busy_pp_head=p;

        }

        p=free_pp_head->next;

        free_pp_head->next=NULL;

        free_pp_head->no_of_vp=page_of_instruction[i];

        vp_array[page_of_instruction[i]].no_of_pp=free_pp_head->no_of_pp;

        if(busy_pp_tail==NULL)

                        busy_pp_head=busy_pp_tail=free_pp_head;

        else

        {

            busy_pp_tail->next=free_pp_head;

            busy_pp_tail=free_pp_head;

        }

        free_pp_head=p;     

    }

    }

    printf("FIFO命中率:%6.4f     ",1-(float)counter_page_default/320);

    return;

}

 

void LRU(int total_pf)

{

    int min,minj,i,j,present_time;//访问时刻

    initialize(total_pf);

    present_time=0;

    for(i=0;i<NUMBER_OF_INSTRUCTION;i++)

    {

    if(vp_array[page_of_instruction[i]].no_of_pp==INVALID)

    {

        counter_page_default++;

        if(free_pp_head==NULL)  //无空闲页面

        {

        min=MAXINT;

        for(j=0;j<NUMBER_OF_VP;j++)

            if(min>vp_array[j].time&&vp_array[j].no_of_pp!=INVALID)

            {

                 min=vp_array[j].time;minj=j;

            }

        free_pp_head=&pp_control[vp_array[minj].no_of_pp];

        vp_array[minj].no_of_pp=INVALID;

        vp_array[minj].time=-1;

        free_pp_head->next=NULL;

        }

        vp_array[page_of_instruction[i]].no_of_pp=free_pp_head->no_of_pp;

        vp_array[page_of_instruction[i]].time=present_time;

        free_pp_head=free_pp_head->next;

    }

    else

        vp_array[page_of_instruction[i]].time=present_time;// 使用

   

    present_time++;

    }

    printf("LRU命中率:%6.4f     ",1-(float)counter_page_default/320);

    return ;

}

 

void initialize(int total_pf)

{

    int i;

    counter_page_default=0;

    for(i=0;i<NUMBER_OF_VP;i++)

    {

                vp_array[i].no_of_vp=i;

                vp_array[i].no_of_pp=INVALID;

                vp_array[i].counter_in_period=0;

                vp_array[i].time=-1;

    }

    for(i=1;i<total_pf;i++)

    {

                pp_control[i-1].next=&pp_control[i];  //建立pp_control[i-1]ptf[i]之间的链接

                pp_control[i-1].no_of_pp=i-1;

    }

    pp_control[total_pf-1].next=NULL;

    pp_control[total_pf-1].no_of_pp=total_pf-1;

    free_pp_head=&pp_control[0];

    return;

}

 

《进(线)程管理》实验指导书

【实验目的】

1.      理解P-V操作的原理;

2.      理解WINDOWS下进程/线程的互斥和同步的实现机制;

【实验要求】

1.      WINDOWS系统中实现生产者和消费者同步和互斥的P-V操作。

【实验内容】

1.      编写和编译一个WIN32控制台应用程序,模拟实现生产者和消费者的同步和互斥问题。

2.      使用文件的方式记录每一个产品(数据)的生产和消费的详细过程,以便事后研究。

【实验背景】

1.      生产者-消费者问题的描述

若干个生产者和消费者共同存取有限大小的缓冲区。存取规则如下:1.生产者或消费者每个时刻只能有1个进程生产或消费1个产品;2.不能向满缓冲区放产品;不能向空缓冲区取产品。

 

2.      WINDOWS下进程的同步和互斥有关函数

2.1       互斥对象(Mutex)

就是互斥信号量,在一个时刻只能被一个线程使用。相关API包括:CreateMutexOpenMutexReleaseMutex CreateMutex创建互斥对象,返回对象句柄;OpenMutex 打开并返回一个已存在的互斥对象句柄,用于后续访问;ReleaseMutex释放对互斥对象的占用,使之成为可用。

2.2       信号量对象(Semaphore

就是资源信号量,初始值的取值范围在0到指定最大值之间,用于限制并发访问的线程数。相关API包括:CreateSemaphoreOpenSemaphoreReleaseSemaphoreCreateSemaphore 创建一个信号量对象,在输入参数中指定初值和最大值,返回对象句柄。OpenSemaphore 打开并返回一个已存在的信号量对象句柄,用于后续访问。ReleaseSemaphore释放对信号量对象的占用,使之成为可用。

【实验步骤】

1.      在生产者-消费者问题中,假设缓冲区的大小为5,生产者个数为1,消费者个数为2

2.      使用VC++6.0创建一个WIN32控制台应用程序,使用WINDOWS进程/线程相关函数解决生产者-消费者PV问题。

3.      可能用到的主要全局变量和函数提供如下参考和定义:

 

 

 

/*************************************************************

*  文件名:Producer_Consumer.cpp

*  创建日期:.10.5

*     者:苏曙光

*  使用者:软件工程级,操作系统实验用

*     能:用PV操作解决生产者-消费者问题(windows版本)

*     述:) 1个生产者,个消费者

*            2) 缓冲区大小:

*            3) 互斥对象:csArray

*                          信号量:hFull

*                          信号量:hEmpty

*

*

**************************************************************/

 

#include "stdafx.h"

#include "stdio.h"

#include <windows.h>

 

#define FILE_LOG

#ifdef FILE_LOG

   FILE * cfileLog;

#endif

 

//缓冲区,大小为

int array[5];

 

//记录生成数据的个数

int pointer;

 

//记录取得的数据的位置

int pointerget;

 

//用来保存数据和

int sum;

 

//临界区对象

CRITICAL_SECTION csArray;

 

//句柄,保存Full信号量

HANDLE hFull;

 

//句柄,保存Empty信号量

HANDLE hEmpty;

 

 

//生产者函数

DWORD WINAPI Producer(LPVOID lpParam)

{

 int i = 0;

 pointer = 0;

 while( i < 100 )

 {

 

  WaitForSingleObject(hEmpty,INFINITE);

  EnterCriticalSection( &csArray);

      array[(pointer++)%5] = i + 1;

          printf("new data: %5d/n",i + 1);

 

  #ifdef FILE_LOG

      char DebugString[100];

          int StringLong;

      sprintf(DebugString,"new data: %5d/n",i + 1);

          StringLong = strlen(DebugString);

          fwrite(DebugString,1,StringLong,cfileLog);

  #endif

 

  LeaveCriticalSection( &csArray);

  ReleaseSemaphore(hFull,1,NULL);

  i++;

 }

 

 return 0;

}

 

//消费者函数A

DWORD WINAPI ConsumerA(LPVOID lpParam)

{

 while(1)

 {

  WaitForSingleObject(hFull,INFINITE);

  EnterCriticalSection( &csArray);

  sum += array[(pointerget ++ )%5];

  printf("        Consumer A get %5d/n",array[(pointerget -1)%5]);

  if(pointerget == 100)

      printf("The sum is %d",sum);

 

  #ifdef FILE_LOG

      char DebugString[100];

          int StringLong;

      sprintf(DebugString,"        Consumer A get %5d/n",array[(pointerget -1)%5]);

          StringLong = strlen(DebugString);

          fwrite(DebugString,1,StringLong,cfileLog);

  #endif

 

  LeaveCriticalSection( &csArray);

  ReleaseSemaphore(hEmpty,1,NULL);

 }

 return 0;

}

 

//消费者函数B

DWORD WINAPI ConsumerB(LPVOID lpParam)

{

 while(1)

 {

  WaitForSingleObject(hFull,INFINITE);

  EnterCriticalSection( &csArray);

  sum += array[(pointerget ++ )%5];

  printf("            Consumer B get %5d /n",array[(pointerget -1 )%5]);

  if(pointerget == 100)

       printf("The sum is %d",sum);

 

  #ifdef FILE_LOG

      char DebugString[100];

          int StringLong;

      sprintf(DebugString,"            Consumer B get %5d /n",array[(pointerget -1 )%5]);

          StringLong = strlen(DebugString);

          fwrite(DebugString,1,StringLong,cfileLog);

  #endif

 

  LeaveCriticalSection( &csArray);

  ReleaseSemaphore(hEmpty,1,NULL);

 }

 return 0;

}

 

int main(int argc, char* argv[])

{

         HANDLE hThreadProducer,hThreadConsumerA,hThreadComsumerB;

         sum = 0;

         pointerget = 0;

    

     #ifdef FILE_LOG

             cfileLog = fopen("生产者_消费者日志.txt","w");

     #endif

         InitializeCriticalSection( &csArray);

         hFull  = CreateSemaphore(NULL, 0, 5, NULL);

         hEmpty = CreateSemaphore(NULL, 5, 5, NULL);

         hThreadProducer  = CreateThread(NULL, 0, Producer,  NULL, 0, NULL);

         hThreadConsumerA = CreateThread(NULL, 0, ConsumerA, NULL, 0, NULL);

         hThreadComsumerB = CreateThread(NULL, 0, ConsumerB, NULL, 0, NULL);

   

         getchar();

     fclose(cfileLog);

         return 0;

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值