POSIX C Threads. Pthread_cond_t example. It does not work properly

I wrote a written program, and it does not work as I expect. I have two threads: thread triggers func and anotherThread triggers anotherFunc . What I wanted to do was when cont reaches 10 in func , anotherThread to run using pthread_cond_wait and pthread_cond_signal . The strange thing is, everything works fine if I uncomment the sleep(1) . I'm new to threads, and I followed the tutorial here , and if I comment on the sleep line in their example, it will also break.

My question is, how can I do this work without sleep() calls? And what happens if in my code both func reaches pthread_mutex_lock after anotherFunc ? How can I control these things? This is my code:

 #include <iostream> #include <stdlib.h> #include <stdio.h> #include <pthread.h> pthread_mutex_t myMutex; pthread_cond_t cond; pthread_attr_t attr; int cont; void *func(void*) { printf("func\n"); for(int i = 0; i < 20; i++) { pthread_mutex_lock(&myMutex); cont++; printf("%d\n", cont); if(cont == 10) { printf("signal:\n"); pthread_cond_signal(&cond); // sleep(1); } pthread_mutex_unlock(&myMutex); } printf("Done func\n"); pthread_exit(NULL); } void *anotherFunc(void*) { printf("anotherFunc\n"); pthread_mutex_lock(&myMutex); printf("waiting...\n"); pthread_cond_wait(&cond, &myMutex); cont += 10; printf("slot\n"); pthread_mutex_unlock(&myMutex); printf("mutex unlocked anotherFunc\n"); printf("Done anotherFunc\n"); pthread_exit(NULL); } int main(int argc, char *argv[]) { pthread_t thread; pthread_t anotherThread; pthread_attr_init(&attr); pthread_mutex_init(&myMutex, NULL); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_cond_init(&cond, NULL); pthread_create(&anotherThread, &attr, anotherFunc, NULL); pthread_create(&thread, &attr, func, NULL); pthread_join(thread, NULL); pthread_join(anotherThread, NULL); printf("Done MAIN()"); pthread_mutex_destroy(&myMutex); pthread_cond_destroy(&cond); pthread_attr_destroy(&attr); pthread_exit(NULL); return 0; } 

Sorry for the long post, but I'm new to streams and I'm ready to learn. Also do you know good links or courses / tutorials on streams and networks on Linux? I want to learn how to create a chat client, and I heard that for this I need to know the topics and networks. The problem is that I do not know very well that what I learn is good, since I do not know what I need to know.

Thank you very much:)

+6
source share
4 answers

Your anotherThread simply calls pthread_cond_wait without first testing to see if the desired condition has occurred (counter reaching ten). This is the wrong logic that will lead to the problem of lost awakening: the name of a repeating error that causes incorrectly written multithreaded programs.

Variable conditions have no state. If pthread_cond_signal or pthread_cond_broadcast is called, provided that none of the threads are executed, the operation has no effect. They don’t remember him. Thus, your signal thread can count on 10 very quickly and signal a condition variable before another thread reaches the pthread_cond_wait call.

You need a loop around pthread_cond_wait . The condition must be checked if it is already true, so that the thread does not wait for an awakening that has already occurred. And it should be a loop because awakenings can be false: just because the thread falls through pthread_cond_wait does not mean that the condition is really true:

 while (cont < 10) pthread_cond_wait(&cond, &myMutex); 

In addition, there is no need to create a stream attribute just to create a stream. This is the default situation when you use a null pointer for a create attribute. POSIX threads can be merged if they are not created separately or transferred to the pthread_detach section.

Other: Avoid calling pthread_cond_signal possible while holding the mutex lock. This is not true, but it is potentially wasteful, because in fact the operation can cause a call to the kernel of the OS to wake up the thread, and therefore you keep this expensive mutex lock throughout the system call (when all you really need is to protect several machine instructions that work with shared data in your application).

+9
source

I don’t know what is your actual problem (what happens when it doesn’t work?) ..

I see one serious problem: you are not handling false awakenings .

You need something that signals that the condition is really true, for example with a boolean variable:

INIT:

 signaled = false; 

signal:

 signaled = true; pthread_cond_signal(&cond); 

we get:

 while (!signaled) pthread_cond_wait(&cond, &myMutex); 
+2
source

What you want is a semaphore, not a condition variable.

The semaphore maintains state and counts wait () and signals () against it.
This is usually done using a condition variable.

Look here for a trivial implementation.

+1
source

This is just an idea, but you can also use semaphores to execute a “trigger”. I remember a project that I was working on a while ago, and what we did while one of our threads was waiting to be launched (using sem_wait), it would just wait an infinite time trying to get a lock (and thus the proc was taken from the scheduler and saving precious cycles). After the main thread was executed with its calculation, it would issue a semaphore, allowing the second thread to perform its calculations.

This is just another alternative.

0
source

Source: https://habr.com/ru/post/913353/


All Articles