pthread_mutex_lock

I am having a hard time getting mutexes to work…

Here’s some code I got from your website, and modified for my testing:

#include <stdio.h>
#include <pthread.h>

// create a mutex
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

// a global variable (we want to protect)
int count = 0;


// thread1
void* function1( void* arg )
{
int tmp = 0;
int i;
int old1, old2;

while( 1 ) {

if(pthread_mutex_lock(&mutex) == -1)
{
perror(“pthread_mutex_lock Error”);
}
// supposedly protected code
old1 = tmp;
tmp = ++count;
old2 = tmp;
pthread_mutex_unlock(&mutex);

// Error or not?
// I expect old1 NOT to equal old2…
if (old1 == old2)
printf(“inc ERROR %d %d\n”, old1, old2);
else
printf(“inc OK %d %d\n”, old1, old2);
printf( “Count is %d\n”, tmp );

// snooze for a time
delay( 200 );
}

return 0;
}


// thread2
void* function2( void* arg )
{
int tmp = 0;
int i;
int old1, old2;

while( 1 ) {
if(pthread_mutex_lock(&mutex) == -1)
{
perror(“pthread_mutex_lock Error”);
}
// supposedly protected code
old1 = tmp;
tmp = --count;
old2 = tmp;

pthread_mutex_unlock(&mutex);
// I expect old1 NOT to equal old2…
if (old1 == old2) printf(“dec ERROR *********\n");
printf( "
Count is %d\n”, tmp );

// snooze for a time
delay( 500 );
}

return 0;
}

int main( void )
{
pthread_create( NULL, NULL, &function1, NULL );
pthread_create( NULL, NULL, &function2, NULL );

// Let the threads run for 60 seconds.
sleep( 60 );

// destroy the mutex
pthread_mutex_destroy(&mutex);

return 0;
}

When I run it, I (unexpectedly) get:


inc OK 0 1
Count is 1
dec ERROR ***********
** Count is 0
inc ERROR 1 1
Count is 1
inc OK 1 2
Count is 2
** Count is 1
inc ERROR 2 2
Count is 2
inc OK 2 3
Count is 3
** Count is 2
inc ERROR 3 3
Count is 3
inc OK 3 4
Count is 4
** Count is 3
inc ERROR 4 4
Count is 4
inc OK 4 5
Count is 5
** Count is 4
inc ERROR 5 5


Could anyone explain why is this happening?
My understanding is that locking the mutex will ‘lock’ all operations in a
section of code, until the mutex is unlocked. Is this incorrect? (i guess
so, but…) What is the correct way to do this?

Thanks,

Mark

The mutex_lock does not ‘lock’ the code. It locks the mutex (from
attempts to lock it again until it is unlocked). You have two threads
running simultaneously, one incrementing a value and another
decrementing it. You print value outside of critical section, so it is
not protected at that time and can be modified by another thread as you
print it.

  • igor

Mark Welo wrote:

I am having a hard time getting mutexes to work…

Here’s some code I got from your website, and modified for my testing:

#include <stdio.h
#include <pthread.h

// create a mutex
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

// a global variable (we want to protect)
int count = 0;

// thread1
void* function1( void* arg )
{
int tmp = 0;
int i;
int old1, old2;

while( 1 ) {

if(pthread_mutex_lock(&mutex) == -1)
{
perror(“pthread_mutex_lock Error”);
}
// supposedly protected code
old1 = tmp;
tmp = ++count;
old2 = tmp;
pthread_mutex_unlock(&mutex);

// Error or not?
// I expect old1 NOT to equal old2…
if (old1 == old2)
printf(“inc ERROR %d %d\n”, old1, old2);
else
printf(“inc OK %d %d\n”, old1, old2);
printf( “Count is %d\n”, tmp );

// snooze for a time
delay( 200 );
}

return 0;
}

// thread2
void* function2( void* arg )
{
int tmp = 0;
int i;
int old1, old2;

while( 1 ) {
if(pthread_mutex_lock(&mutex) == -1)
{
perror(“pthread_mutex_lock Error”);
}
// supposedly protected code
old1 = tmp;
tmp = --count;
old2 = tmp;

pthread_mutex_unlock(&mutex);
// I expect old1 NOT to equal old2…
if (old1 == old2) printf(“dec ERROR *********\n");
printf( "
Count is %d\n”, tmp );

// snooze for a time
delay( 500 );
}

return 0;
}

int main( void )
{
pthread_create( NULL, NULL, &function1, NULL );
pthread_create( NULL, NULL, &function2, NULL );

// Let the threads run for 60 seconds.
sleep( 60 );

// destroy the mutex
pthread_mutex_destroy(&mutex);

return 0;
}

When I run it, I (unexpectedly) get:

inc OK 0 1
Count is 1
dec ERROR ***********
** Count is 0
inc ERROR 1 1
Count is 1
inc OK 1 2
Count is 2
** Count is 1
inc ERROR 2 2
Count is 2
inc OK 2 3
Count is 3
** Count is 2
inc ERROR 3 3
Count is 3
inc OK 3 4
Count is 4
** Count is 3
inc ERROR 4 4
Count is 4
inc OK 4 5
Count is 5
** Count is 4
inc ERROR 5 5

Could anyone explain why is this happening?
My understanding is that locking the mutex will ‘lock’ all operations in a
section of code, until the mutex is unlocked. Is this incorrect? (i guess
so, but…) What is the correct way to do this?

Thanks,

Mark

“Igor Kovalenko” <Igor.Kovalenko@motorola.com> wrote in message
news:3A5B868C.1C994B24@motorola.com

The mutex_lock does not ‘lock’ the code. It locks the mutex (from
attempts to lock it again until it is unlocked). You have two threads
running simultaneously, one incrementing a value and another
decrementing it. You print value outside of critical section, so it is
not protected at that time and can be modified by another thread as you
print it.

  • igor

Yes, I agree. I’ve tried printing the values before the unlock, but it
seems to have no effect. I’m printing the values of old1 and old2 which
cannot be changed by the other thread. They’re just local variables on the
stack… Now, maybe the compiler is playing games here, but I don’t think
so.

Mark Welo wrote:

I am having a hard time getting mutexes to work…

Here’s some code I got from your website, and modified for my testing:

#include <stdio.h
#include <pthread.h

// create a mutex
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

// a global variable (we want to protect)
int count = 0;

// thread1
void* function1( void* arg )
{
int tmp = 0;
int i;
int old1, old2;

while( 1 ) {

if(pthread_mutex_lock(&mutex) == -1)
{
perror(“pthread_mutex_lock Error”);
}
// supposedly protected code
old1 = tmp;
tmp = ++count;
old2 = tmp;
pthread_mutex_unlock(&mutex);

// Error or not?
// I expect old1 NOT to equal old2…
if (old1 == old2)
printf(“inc ERROR %d %d\n”, old1, old2);
else
printf(“inc OK %d %d\n”, old1, old2);
printf( “Count is %d\n”, tmp );

// snooze for a time
delay( 200 );
}

return 0;
}

// thread2
void* function2( void* arg )
{
int tmp = 0;
int i;
int old1, old2;

while( 1 ) {
if(pthread_mutex_lock(&mutex) == -1)
{
perror(“pthread_mutex_lock Error”);
}
// supposedly protected code
old1 = tmp;
tmp = --count;
old2 = tmp;

pthread_mutex_unlock(&mutex);
// I expect old1 NOT to equal old2…
if (old1 == old2) printf(“dec ERROR *********\n");
printf( "
Count is %d\n”, tmp );

// snooze for a time
delay( 500 );
}

return 0;
}

int main( void )
{
pthread_create( NULL, NULL, &function1, NULL );
pthread_create( NULL, NULL, &function2, NULL );

// Let the threads run for 60 seconds.
sleep( 60 );

// destroy the mutex
pthread_mutex_destroy(&mutex);

return 0;
}

When I run it, I (unexpectedly) get:

inc OK 0 1
Count is 1
dec ERROR ***********
** Count is 0
inc ERROR 1 1
Count is 1
inc OK 1 2
Count is 2
** Count is 1
inc ERROR 2 2
Count is 2
inc OK 2 3
Count is 3
** Count is 2
inc ERROR 3 3
Count is 3
inc OK 3 4
Count is 4
** Count is 3
inc ERROR 4 4
Count is 4
inc OK 4 5
Count is 5
** Count is 4
inc ERROR 5 5

Could anyone explain why is this happening?
My understanding is that locking the mutex will ‘lock’ all operations in
a
section of code, until the mutex is unlocked. Is this incorrect? (i
guess
so, but…) What is the correct way to do this?

Thanks,

Mark

Mark Welo <mwelo@logisync.com> wrote:

: “Igor Kovalenko” <Igor.Kovalenko@motorola.com> wrote in message
: news:3A5B868C.1C994B24@motorola.com
:> The mutex_lock does not ‘lock’ the code. It locks the mutex (from
:> attempts to lock it again until it is unlocked). You have two threads
:> running simultaneously, one incrementing a value and another
:> decrementing it. You print value outside of critical section, so it is
:> not protected at that time and can be modified by another thread as you
:> print it.
:>
:> - igor

: Yes, I agree. I’ve tried printing the values before the unlock, but it
: seems to have no effect. I’m printing the values of old1 and old2 which
: cannot be changed by the other thread. They’re just local variables on the
: stack… Now, maybe the compiler is playing games here, but I don’t think
: so.

No your code is flawed because you are making assumptions; expecting that
the threads will run alternatively. Mutexes only protect the acess of some
share data, but not the scheduling policy. To acheive what you want you
should use predicates or condition variable to signal the other thread that
it is its turn to enter etc …

Also the return value of pthread_mutex_XXX ( ) are worng, look at the docs.


au revoir, alain

Aussi haut que l’on soit assis, on n’est toujours assis que sur son cul !!!

Thanks, Igor, for the insight.
I’ll just save everyone some time and answer my own question. Although it
APPEARS at first sight that the code isn’t working, after further ‘thought’
I have realized the error of my ways. My increment thread code is written
like this:

if(pthread_mutex_lock(&mutex) == -1)
{
perror(“pthread_mutex_lock Error”);
}
// supposedly protected code
old1 = tmp;
tmp = ++count;
old2 = tmp;
pthread_mutex_unlock(&mutex);

Now after it has incremented count, the decrement thread decrements it
(count). The variable tmp is still set to the incremented value, and so my
test for old1 == old2 is invalid. old1 should be set to count and old2
should also be set to count (or tmp, I guess). Then the test would work.
Now why couldn’t I see that an hour ago?

“Mark Welo” <mwelo@logisync.com> wrote in message
news:93g1h0$8k$1@inn.qnx.com

“Igor Kovalenko” <> Igor.Kovalenko@motorola.com> > wrote in message
news:> 3A5B868C.1C994B24@motorola.com> …
The mutex_lock does not ‘lock’ the code. It locks the mutex (from
attempts to lock it again until it is unlocked). You have two threads
running simultaneously, one incrementing a value and another
decrementing it. You print value outside of critical section, so it is
not protected at that time and can be modified by another thread as you
print it.

  • igor

Yes, I agree. I’ve tried printing the values before the unlock, but it
seems to have no effect. I’m printing the values of old1 and old2 which
cannot be changed by the other thread. They’re just local variables on
the
stack… Now, maybe the compiler is playing games here, but I don’t think
so.


Mark Welo wrote:

I am having a hard time getting mutexes to work…

Here’s some code I got from your website, and modified for my testing:

#include <stdio.h
#include <pthread.h

// create a mutex
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

// a global variable (we want to protect)
int count = 0;

// thread1
void* function1( void* arg )
{
int tmp = 0;
int i;
int old1, old2;

while( 1 ) {

if(pthread_mutex_lock(&mutex) == -1)
{
perror(“pthread_mutex_lock Error”);
}
// supposedly protected code
old1 = tmp;
tmp = ++count;
old2 = tmp;
pthread_mutex_unlock(&mutex);

// Error or not?
// I expect old1 NOT to equal old2…
if (old1 == old2)
printf(“inc ERROR %d %d\n”, old1, old2);
else
printf(“inc OK %d %d\n”, old1, old2);
printf( “Count is %d\n”, tmp );

// snooze for a time
delay( 200 );
}

return 0;
}

// thread2
void* function2( void* arg )
{
int tmp = 0;
int i;
int old1, old2;

while( 1 ) {
if(pthread_mutex_lock(&mutex) == -1)
{
perror(“pthread_mutex_lock Error”);
}
// supposedly protected code
old1 = tmp;
tmp = --count;
old2 = tmp;

pthread_mutex_unlock(&mutex);
// I expect old1 NOT to equal old2…
if (old1 == old2) printf(“dec ERROR *********\n");
printf( "
Count is %d\n”, tmp );

// snooze for a time
delay( 500 );
}

return 0;
}

int main( void )
{
pthread_create( NULL, NULL, &function1, NULL );
pthread_create( NULL, NULL, &function2, NULL );

// Let the threads run for 60 seconds.
sleep( 60 );

// destroy the mutex
pthread_mutex_destroy(&mutex);

return 0;
}

When I run it, I (unexpectedly) get:

inc OK 0 1
Count is 1
dec ERROR ***********
** Count is 0
inc ERROR 1 1
Count is 1
inc OK 1 2
Count is 2
** Count is 1
inc ERROR 2 2
Count is 2
inc OK 2 3
Count is 3
** Count is 2
inc ERROR 3 3
Count is 3
inc OK 3 4
Count is 4
** Count is 3
inc ERROR 4 4
Count is 4
inc OK 4 5
Count is 5
** Count is 4
inc ERROR 5 5

Could anyone explain why is this happening?
My understanding is that locking the mutex will ‘lock’ all operations
in
a
section of code, until the mutex is unlocked. Is this incorrect? (i
guess
so, but…) What is the correct way to do this?

Thanks,

Mark