简体   繁体   中英

No prints from the second thread - pthreads with mutex locks

I wrote:

#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;

int globalVarX;

void *threadFunction (void *arg)
{
    pthread_mutex_lock (&mutex1);

    while (globalVarX < 1000)
    {
        printf("x increment by thread id: %d", gettid ());
        ++globalVarX;
    }

    pthread_mutex_unlock (&mutex1);

    return NULL;
}

int main()
{
    pthread_t threadA;
    pthread_t threadB;

    if (pthread_create (&threadA, NULL, threadFunction, NULL)) 
    {
        fprintf (stderr, "Error creating thread\n");
        return 1;
    }

    if (pthread_create (&threadB, NULL, threadFunction, NULL)) 
    {
        fprintf (stderr, "Error creating thread\n");
        return 1;
    }

    if (pthread_join (threadA, NULL))
    {
        fprintf (stderr, "Error joining thread\n");
        return 2;
    }

    if (pthread_join (threadB, NULL))
    {
        fprintf (stderr, "Error joining thread\n");
        return 2;
    }

    return 0;
}

Prints I am getting are as follows:

~/studies$ ./a.out 
x increment by thread id: 3154
x increment by thread id: 3154
x increment by thread id: 3154
x increment by thread id: 3154
x increment by thread id: 3154
x increment by thread id: 3154
x increment by thread id: 3154
x increment by thread id: 3154
x increment by thread id: 3154
x increment by thread id: 3154
~/studies$ 

Prints from the other thread are not shown.

The first thread increments globalVarX to 1000 and the second thread has nothing to do.

I suggest:

  • Locking one increment instead of the whole loop.

  • Give the other thread the opportunity to increment also by calling sched_yield() , because if one thread increments globalVarX to 1000 in its time slice there still would be no prints from the second thread.

#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <unistd.h>

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;

int globalVarX;

void *threadFunction (void *arg)
{
    int flagbreak = 0;

    for(;!flagbreak;) {
        pthread_mutex_lock (&mutex1);
        if (globalVarX >= 1000) flagbreak = 1;
        else {
            ++globalVarX;
            printf("x increment by thread id: %ld\n", syscall(SYS_gettid));
        }
        pthread_mutex_unlock (&mutex1);
        sched_yield();
    }
    return NULL;
}

int main(void)
{
    pthread_t threadA;
    pthread_t threadB;

    if (pthread_create (&threadA, NULL, threadFunction, NULL)) 
    {
        fprintf (stderr, "Error creating thread\n");
        return 1;
    }

    if (pthread_create (&threadB, NULL, threadFunction, NULL)) 
    {
        fprintf (stderr, "Error creating thread\n");
        return 1;
    }

    if (pthread_join (threadA, NULL))
    {
        fprintf (stderr, "Error joining thread\n");
        return 2;
    }

    if (pthread_join (threadB, NULL))
    {
        fprintf (stderr, "Error joining thread\n");
        return 2;
    }

    return 0;
}

To conceptually give both threads a chance on incrementing the counter use this:

Pseudo code:

Condition cond = condition_init;
Mutex mutex = mutex_init;

int counter = 0;

thread_func
{
  mutex_lock(mutex);

  while (counter < 1000)
  {
    ++counter;
    print thread, counter;
    condition_signal(cond);
    condition_wait(cond, mutex);
  }  

  condition_signal(cond);

  mutex_unlock(mutex);
}

main
{
  Thread thread_a = thread_create(thread_func);
  Thread thread_b = treadd_create(thread_func);

  thread_join(thread_a);
  thread_join(thread_b);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM