Alex D.
Alex D.

Reputation: 23

Mutex does not work as expected

I have used mutex in inherited classes but seems it does not work as I expected with threads. Please have a look at below code:

#include <iostream>
#include <cstdlib>
#include <pthread.h>

// mutex::lock/unlock
#include <iostream>       // std::cout
#include <thread>         // std::thread
#include <chrono>         // std::thread
#include <mutex>          // std::mutex

typedef unsigned int UINT32t;
typedef int INT32t;

using namespace std;



class Abstract {

protected:
    std::mutex mtx;
};


class Derived: public Abstract
{
public:
    void* write( void* result)
    {
        UINT32t error[1];
        UINT32t data = 34;
        INT32t length = 0;
        static INT32t counter = 0;

        cout << "\t   before Locking ..." << " in thread"  << endl;

        mtx.lock();
        //critical section
        cout << "\t    After Create " << ++ counter  << " device in thread"  << endl;

        std::this_thread::sleep_for(1s);

        mtx.unlock();
        cout << "\t    deallocated " << counter << " device in thread"  << endl;
        pthread_exit(result);
    }
};

void* threadTest1( void* result)
{
    Derived dev;

    dev.write(nullptr);
}


int main()
{
    unsigned char byData[1024] = {0};
    ssize_t len;
    void *status = 0, *status2 = 0;
    int result = 0, result2 = 0;

    pthread_t pth, pth2;
    pthread_create(&pth, NULL, threadTest1, &result);
    pthread_create(&pth2, NULL, threadTest1, &result2);


    //wait for all kids to complete
    pthread_join(pth, &status);
    pthread_join(pth2, &status2);

    if (status != 0) {
           printf("result : %d\n",result);
       } else {
           printf("thread failed\n");
       }


    if (status2 != 0) {
           printf("result2 : %d\n",result2);
       } else {
           printf("thread2 failed\n");
       }


    return -1;
}

so the result is:

*Four or five arguments expected.

   before Locking ... in thread
    After Create 1 device in thread
   before Locking ... in thread
    After Create 2 device in thread
    deallocated 2 device in thread
    deallocated 2 device in thread
       thread failed
       thread2 failed

*

So here we can see that second thread comes to critical section before mutex was deallocated. The string "After Create 2 device in thread" says about that. If it comes to critical section before mutex is deallocated it means mutex works wrong.

If you have any thoughts please share.

thanks

Upvotes: 1

Views: 3845

Answers (3)

cdhowie
cdhowie

Reputation: 169008

Edit: tkausl's answer is correct -- however, even if you switch to using a global mutex, the output may not change because of the detail in my answer so I'm leaving it here. In other words, there are two reasons why the output may not be what you expect, and you need to fix both.


Note in particular these two lines:

mtx.unlock();
cout << "\t    deallocated " << counter << " device in thread"  << endl;

You seem to be under the impression that these two lines will be run one right after the other, but there is no guarantee that this will happen in a preemptive multithreading environment. What can happen instead is that right after mtx.unlock() there could be a context switch to the other thread.

In other words, the second thread is waiting for the mutex to unlock, but the first thread isn't printing the "deallocated" message before the second thread preempts it.

The simplest way to get the output you expect would be to swap the order of these two lines.

Upvotes: 4

RoiHatam
RoiHatam

Reputation: 896

You shall declare your mutex as a global variable and initiate it before calling pthread_create. You created two threads using pthread_create and both of them create their own mutex so there is absolutely no synchronization between them.

Upvotes: 2

tkausl
tkausl

Reputation: 14279

The mutex itself is (probably) working fine (I'd recommend you to use std::lock_guard though), but both threads create their own Derived object, hence, they don't use the same mutex.

Upvotes: 6

Related Questions