Thread: mutex_lock troubles

  1. #1
    Registered User
    Join Date
    Feb 2015
    Posts
    1

    Unhappy mutex_lock troubles

    Hi guys, little trouble with mutex locking. I have most of the logic down for this, but I think I've become tangled up in the process. The idea is to have a "producer" making pieces of data (there is a finite amount that can be made, and when this is reached, the producer ends) and a set of "consumers" eating the data. There can only be so much data present at any one time, so when that limit is reached, the producer pauses producing. When there is no data left, the consumers stop consuming.

    My problem comes when I find that the code as it stands works some of the time, and others, the mutex locking causes the code to pause, each thread waiting for the lock to unlock "from what I can tell". I was hoping I could get a couple of pairs of fresh eyes on this, as I've been looking at it all week with limited success. I've also used a couple of defines at the start for my own benefit, to reduce the apparent complexity of the code.

    Code:
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    typedef enum {FALSE,TRUE} boolean;
    
    
    
    
    #define                         NUMCONSUMERS        2
    #define                         NUMPRODUCERS        1
    #define                    PACKETS            10
    #define                    tryMainlock        pthread_mutex_trylock(&dataMutex)
    #define                    takeMainlock        pthread_mutex_lock(&dataMutex)
    #define                    releaseMainlock        pthread_mutex_unlock(&dataMutex)
    #define                    waitMainlock        pthread_cond_wait(&dataPresentCondition, &dataMutex);
    #define                    signalMainlock        pthread_cond_signal(&dataPresentCondition);
    
    
    #define                    trydatalock        pthread_mutex_trylock(&IsthereDataleft)
    #define                    takedatalock        pthread_mutex_lock(&IsthereDataleft)
    #define                    releasedatalock        pthread_mutex_unlock(&IsthereDataleft)
    
    
    pthread_mutex_t                 dataMutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t                  dataPresentCondition = PTHREAD_COND_INITIALIZER;
    
    
    pthread_mutex_t                IsthereDataleft = PTHREAD_MUTEX_INITIALIZER;
    
    
    int                    sharedData=0;    //amount of data present
    int                     BUFFER = 5;
    int                    dataleft=PACKETS;
    int                    finish = 1;
    
    
    
    
    
    
    
    
    
    
    void *Producer(void *threadid){
        int rc;
        printf("Producer Thread %x: Created\n", (int)threadid);
        while (1)
        {
            printf("Producer %x: Attempting to take lock...\n", (int)threadid);
            rc = takeMainlock;            //take hold of the lock
            if (!dataleft)                //If there's no data left to add to the stream, close the thread
            {
                printf("Producer Thread %x: Completed, exiting...\n", (int)threadid);
                rc = releaseMainlock;    
                rc = signalMainlock;
                rc = takedatalock;
                finish = 0;
                rc = releasedatalock;
                return NULL;
            }
            while (sharedData == BUFFER)
            {
                printf("Buffer is full\n");
                rc = releaseMainlock;    
                rc = pthread_cond_broadcast(&dataPresentCondition);
                if (rc)
                {
                    printf("........s ........ed up yo.\n");
                }
                printf("Producer Thread %x: Waiting for lock...\n", (int) threadid);
                rc = waitMainlock;
                if (rc)
                {
                    printf("........s ........ed yo.\n");
                }
            }
            printf("Producer %x: Lock Acquired-----------------------------------------\n", (int)threadid);
            sharedData++;
            dataleft--;
            rc = releaseMainlock;
            rc = signalMainlock;
            if (rc)
                {
                    printf("........s ........ed yo.\n");
                }
            printf("Producer %x: Releasing Lock++++++++++++++++++\n", (int)threadid);
        }
    }
    
    
    
    
    void *Consumer(void *threadid){
        int rc;
        printf("Consumer Thread %x: Created\n", (int)threadid);
        while (1)
        {
            printf("Consumer %x: Attempting to take Main lock...\n",(int) threadid);
            rc = takeMainlock;        //take hold of main lock
            printf("Consumer %x: Lock Acquired**********************************************\n", (int)threadid);
            while (sharedData == 0)        //if the buffer is empty
            {
                printf("Consumer %x: Shared Data is 0+++++++++++++++++++++++++++++\n", (int) threadid);
                rc = releaseMainlock;    
                rc = signalMainlock;
                if (rc)
                {
                    printf("........s ........ed yo.\n");
                }        
                rc = takedatalock;
                if (!finish)
                {
                    rc = releaseMainlock;
                    rc = signalMainlock;
                    rc = releasedatalock;
                    printf("Consumer %x: Completed. Exiting...\n",(int) threadid);
                    return NULL;
                }
                rc = releasedatalock;
                printf("Consumer %x: Data still left to process. Waiting for unlock...\n", (int) threadid);
                rc = waitMainlock;
                printf("Consumer %x: Waiting Period Finished\n", (int) threadid);
                if (rc)
                {
                    printf("........s ........ed yo.\n");
                }
            }
            printf("Consumer %x: Lock Acquired**********************************************\n", (int)threadid);
            sharedData--;
            rc = releaseMainlock;
            rc = pthread_cond_broadcast(&dataPresentCondition);
            if (rc)
                {
                    printf("........s ........ed yo.\n");
                }
            printf("Consumer %x: Releasing Lock+++++++++++++++++\n", (int)threadid);            
        }
    }
    
    
    
    
    
    
    
    
    int main(int argc, char **argv)
    {
        int rc;                        //error checking
        int i;
        pthread_t  consumer[NUMCONSUMERS];
        pthread_t  producer[NUMPRODUCERS];
        rc = takedatalock;                //lock to determine whether there's any point waiting for data
        for (i=0; i <NUMPRODUCERS; i++) {        //Build up the producers
            rc = pthread_create(&producer[i], NULL, Producer, (void *)i);
            if (rc)
                printf("Error building Producer Thread: %x\n", i);
        }
        
        for (i=0; i <NUMCONSUMERS; i++) {        //Build up the consumers
            rc = pthread_create(&consumer[i], NULL, Consumer, (void *)i);
            if (rc)
                printf("Error building Consumer Thread: %x\n", i);
        }
    
    
        printf("All Producers and Consumers created\n");
        
        for (i=0; i <NUMPRODUCERS; i++) {        //Join up the producers
            rc = pthread_join(producer[i], NULL);
            if (rc)
                printf("Error: Producer %x: Failed to join\n", i);
        }
        rc = releasedatalock;                //producers finished, no data left to make
        
        printf("datalock closed, consumers finishing...\n");
        
        rc = pthread_cond_broadcast(&dataPresentCondition);
        for (i=0; i <NUMCONSUMERS; i++) {        //Join up the consumers
            rc = pthread_join(consumer[i], NULL);
            printf("Consumer %x: Joined correctly!\n", i);
            if (rc)
                printf("Error: Consumer %x: Failed to join\n", i);
        }
        rc = pthread_mutex_destroy(&dataMutex);
        rc = pthread_cond_destroy(&dataPresentCondition);
        rc = pthread_mutex_destroy(&IsthereDataleft);
    
    
        printf("All Threads finished. Exiting....\n");
        return 0;
    }
    As I said, its probably something small, but I can't quite see it anymore for all the other code. I get the feeling that its something to do with the buffer, as there are times where the Consumers will simply never try to use the data, and when the producer reaches the buffer, it is also stuck.

    There is also a chance there is a separate problem when it comes to the ending of the threads as well, as it can be the case that one consumer will exit having found there is nothing left to consume, and the rest will be trapped in limbo.

    I've attached a downloadable version to this post as well. Cheers Lads.
    Attached Files Attached Files
    • File Type: c pr.c (5.3 KB, 149 views)

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    A couple of tips.

    > #define tryMainlock pthread_mutex_trylock(&dataMutex)
    1. Don't use the pre-processor to save your typing. It makes the code unnecessarily hard for anyone other than you to read in any sensible fashion.

    > printf("........s ........ed yo.\n");
    Keep your profanity to yourself when you publish code for others to read.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. troubles in using GDB
    By leiming in forum C Programming
    Replies: 7
    Last Post: 04-18-2008, 01:54 AM
  2. tic tac toe troubles...
    By mkylman in forum Game Programming
    Replies: 8
    Last Post: 09-16-2006, 06:44 PM
  3. GTK troubles...again...
    By cornholio in forum Linux Programming
    Replies: 4
    Last Post: 01-16-2006, 01:37 AM
  4. NIC Troubles?
    By Bajanine in forum Tech Board
    Replies: 4
    Last Post: 05-16-2004, 04:45 PM
  5. .AVI troubles
    By Untitled1 in forum Tech Board
    Replies: 6
    Last Post: 10-26-2003, 10:39 AM

Tags for this Thread