Click here to Skip to main content
Click here to Skip to main content
Go to top

Semaphore Example

, 13 Feb 2013
Rate this:
Please Sign up or sign in to vote.
A Semaphore example.

Semaphore_Ex

Introduction

This is sample program to explain how semaphores work. I have taken the production and consumption logic to explain the working of semaphores. As you know, semaphores are used for resource counting. Here, always the number of produced units is 10 greater than the consumption, i.e., a buffer of 10 is always maintained. The buffer can't go beyond 10. Similarly the consumption can't exceed the production.

Background

A user who starts to work on thread synchronization can take this as a starting point to go. I have taken a simple program.

Using the code

This application has a dialog. And there are two threads which individually run to the production/consumption. These threads can be controlled by two events to start/stop. When the production is started, the thread runs and it checks that the buffer has reached the size of 10. If not, the thread continues to do production, otherwise it stops...

Similarly when the consumption is started, it starts to consume from the buffer. As the consumption is being done continuously, both production and consumption run simultaneously. When the consumption stops, the buffer will reach a size of 10 [on waiting on the semaphore] and the production is stopped automatically.

When the production is stopped, the consumption thread can take a maximum of 10 from the buffer and after that the consumption is stopped as the buffer is zeroed [on waiting on the semaphore]. As some of you mentioned, I missed the explanation on the semaphore [that's is the objective of the article!!!!].

As I said, we have production and consumption threads. There are two semaphore objects which control the resource counts. One is to account the production units m_hProduction and the other is meant for the consumption m_hCustomer.

The production thread is created with an initial count of 0 and a max count of 10. As it is created with an initial count of 0, this is in a non-signaled state.

The consumption semaphore object is created with an initial count of 10 and a max count 10. So this is signaled.

Now let me talk about how the threads use this object....

As we know, the customer semaphore is initially in the signaled state. So the production thread successfully passes the first check. Now when the start button of the production thread is pressed, the production event becomes signaled and the thread does the production. After doing the production, the current count of the production semaphore is increased by 1 and the thread again waits for the customer semaphore. If it is signaled then the loop continues, otherwise it waits till the customer semaphore is signaled. Each time as the thread waiting on the semaphore is being scheduled [because the semaphore is in signaled state], the current resource count of the customer is decreased by one. Here the current count of the customer semaphore is decreased by one. So the loop can iterate 10 times, and after that the current count of the customer semaphore goes to 0, and the production thread goes into a wait state.... Now the current count of production is raised to 10.

Now say, the start button of the consumption thread is started. So the consumption event is signaled. Now the consumption thread waiting on the production semaphore is scheduled as it is in the signaled state. After doing the consumption, it increases the consumption semaphore by 1 and it waits on the production semaphore. If the consumption thread is scheduled over waiting for the production semaphore, the current count of the production semaphore is decreased by 1.

I'll explain two cases here:

  1. The production thread is started and it runs till cur.count of the production semaphore is 10. Now press the stop button to make the production event to non signaled. Now the production thread is waiting. Now start the consumption thread. Here the production semaphore's cur.count is 10 and this thread can iterate 10 times [to consume 10 units] and now the production semaphore's cur.count becomes 0 and the consumption thread is stopped. So now both the threads get stopped.
  2. Both the threads are running parallel. The production semaphore is signaled by the production thread, so the consumption thread waiting on the production semaphore is scheduled. As the consumption thread is scheduled, it signals the consumption semaphore, so the production thread waiting on this object is scheduled. So both threads run simultaneously. Production and consumption happen in parallel.
unsigned WINAPI Production(PVOID dlgPtr )
{
    CSemaphore_ExDlg* pDlg = (CSemaphore_ExDlg*)(dlgPtr);

    //Do the production if there is any customer request. Otherwise wait for the
    //customer's request
    DWORD res = WaitForSingleObject( m_hCustomer,INFINITE );

    //if the object is signaled, do the production
    int i = 0, j = 0;
    static int Ctr = 0;
    while ( res == WAIT_OBJECT_0 )
    {
        //Check for the production event signal
        WaitForSingleObject( hEventProd, INFINITE );

        containerArray[j++] = i++;
        Ctr++;

        g_Var++;
        CString str;
        str.Format("%d", g_Var );
        pDlg->m_statNew.SetWindowText( str );

        //Set the value in the progress bar
        (pDlg->m_ctrlProd).SetValue( Ctr );
        
        if( j >= MAX_ELEMENTS )
            j = j % MAX_ELEMENTS;

    
        //Production is done. So signal the customer 
        LONG pOldVal;
        ReleaseSemaphore( m_hProduction,1,&pOldVal );

        //Do the production continuously
        res = WaitForSingleObject( m_hCustomer,INFINITE );
        Sleep( 50 );

    }

    return 0;
} 

unsigned WINAPI Consumption(PVOID dlgPtr )
{
    CSemaphore_ExDlg* pDlg = (CSemaphore_ExDlg*)(dlgPtr);

    //Consume the product if already some produced goods are available
    DWORD res = WaitForSingleObject( m_hProduction,INFINITE );

    //if the object is signaled, do the production
    int i = 0, j = 0;
    static int Ctr = 0;
    while ( res == WAIT_OBJECT_0 )
    {
        //Check for the consumer event object
        WaitForSingleObject( hEventCons, INFINITE );

        containerArray[j++] = -1;
        Ctr++;

        (pDlg->m_ctrlCons).SetValue(Ctr );

        if( j >= MAX_ELEMENTS )
            j = j % MAX_ELEMENTS;

        //Consumption is done. So signal the empty object
        ReleaseSemaphore( m_hCustomer,1,0 );

        //Do the consumption continuously
        res = WaitForSingleObject( m_hProduction,INFINITE );
        Sleep( 50 );
    }

    return 0;
}

I find this code explains more clearly about how semaphores work.

History

This is the second version. As the first version was missing the explanation, I have added it. Please let me if you need more.....

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Babu_Abdulsalam
Software Developer
India India
I'm working as Senior software Engineer since 7 years and interested in MFC and COM programming.

Comments and Discussions

 
QuestionUnable to compile PinmemberMember 998382812-Apr-13 7:15 
GeneralMy vote of 2 PinmemberAlexander Müller21-Jan-10 9:36 
GeneralRe: My vote of 2 Pinmemberyafan21-Jan-10 12:25 
GeneralRe: My vote of 2 Pinmembersyed_babu21-Jan-10 18:35 
GeneralMy vote of 1 PinmvpRichard MacCutchan21-Jan-10 7:15 
GeneralRe: My vote of 1 Pinmembersyed_babu21-Jan-10 18:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 13 Feb 2013
Article Copyright 2010 by Babu_Abdulsalam
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid