Execution of pthreads in particular order? - c

I am been trying to write a program (for learning) in which there will be two threads (A and B) and both threads should execute one after the another. For example, if threads just display/prints Thread A and Thread B, then they should print in that particular order forever.
The desired output is
In Thread: thread1
In Thread: thread2
In Thread: thread1
In Thread: thread2
....
The program that I have wrote uses conditional variables for synchronisation. I have tired mutex and semaphore but they do guarantee mutual exclusivity but they don't print the information in a particular order. I understand that issue is related to scheduling of the threads by scheduler and it is possible that the thread which has just released the mutex, can lock it again immediately. See this link for link for more information.
#include <stdio.h>
#include <ctype.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
pthread_cond_t cond;
pthread_mutex_t mutex;
int thread1_ret = 0;
void *thread1(void *arg)
{
while (1) {
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
printf("In Thread: %s\r\n", __func__);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
thread1_ret = 5;
return &thread1_ret;
}
int thread2_ret = 0;
void *thread2(void *arg)
{
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
while (1) {
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
printf("In Thread: %s\r\n", __func__);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
thread2_ret = 5;
return &thread2_ret;
}
int main(int argc, char *argv[])
{
pthread_t t1, t2;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_cond_init(&cond, NULL);
pthread_mutex_init(&mutex, NULL);
pthread_create(&t1, &attr, thread1, NULL);
pthread_create(&t2, &attr, thread2, NULL);
pthread_attr_destroy(&attr);
void *ret;
pthread_join(t1, &ret);
printf("Thread Returned: %d\r\n", *(int *)ret);
pthread_join(t2, &ret);
printf("Thread Returned: %d\r\n", *(int *)ret);
return 0;
}
My program is working properly but it stops printing after some time (2-3 seconds). I couldn't locate the bug in my code. It would be great if someone direct me with some other solution to achieve the same thing in more efficient and standard method (if there are other standard and efficient methods to solve such problem statement).

Condition variable notifications get lost when no thread is waiting in pthread_cond_wait and spurious wakes-ups happen, so the code must rather wait for a change of a shared state.
Working example:
#include <stdio.h>
#include <ctype.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
unsigned state = 0;
int thread1_ret = 0;
void *thread1(void *arg)
{
unsigned state_copy;
pthread_mutex_lock(&mutex);
state_copy = state;
pthread_mutex_unlock(&mutex);
while(1) {
pthread_mutex_lock(&mutex);
while(state_copy == state)
pthread_cond_wait(&cond, &mutex);
state_copy = ++state;
printf("In Thread: %s\r\n", __func__);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
thread1_ret = 5;
return &thread1_ret;
}
int thread2_ret = 0;
void *thread2(void *arg)
{
unsigned state_copy;
pthread_mutex_lock(&mutex);
state_copy = ++state;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
while (1) {
pthread_mutex_lock(&mutex);
while(state_copy == state)
pthread_cond_wait(&cond, &mutex);
state_copy = ++state;
printf("In Thread: %s\r\n", __func__);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
thread2_ret = 5;
return &thread2_ret;
}
int main(int argc, char *argv[])
{
pthread_t t1, t2;
pthread_create(&t1, NULL, thread1, NULL);
pthread_create(&t2, NULL, thread2, NULL);
void *ret;
pthread_join(t1, &ret);
printf("Thread Returned: %d\r\n", *(int *)ret);
pthread_join(t2, &ret);
printf("Thread Returned: %d\r\n", *(int *)ret);
return 0;
}
Note that the above code signals the condition variable after releasing the mutex. That is a micro-optimization, however, if FIFO order in waking up waiting threads is required then the mutex must be locked while signalling. See pthread_cond_signal:
The pthread_cond_broadcast() or pthread_cond_signal() functions may be called by a thread whether or not it currently owns the mutex that threads calling pthread_cond_wait() or pthread_cond_timedwait() have associated with the condition variable during their waits; however, if predictable scheduling behavior is required, then that mutex shall be locked by the thread calling pthread_cond_broadcast() or pthread_cond_signal().

Related

will mutex be unlock after thread terminate?

On my debian 11, I created two thread, canceld one of them and joined them.
#include <stdio.h>
#include <pthread.h>
#include <assert.h>
#include <unistd.h>
#include <signal.h>
pthread_mutex_t executant;
void *func_1 (void *arg)
{
for (;;) {
pthread_mutex_lock (&executant);
printf ("1\n");
sleep(1);
pthread_mutex_unlock (&executant);
}
return NULL;
}
void *func_2 (void *arg)
{
for (;;) {
pthread_mutex_lock (&executant);
printf ("222\n");
sleep(1);
pthread_mutex_unlock (&executant);
}
return NULL;
}
int main (void)
{
pthread_t thread_1, thread_2;
pthread_mutex_init (&executant, NULL);
pthread_mutex_lock (&executant);
assert (pthread_create (&thread_1, NULL, func_1, NULL) == 0);
assert (pthread_create (&thread_2, NULL, func_2, NULL) == 0);
pthread_mutex_unlock (&executant);
pthread_cancel (thread_1);
pthread_join (thread_1, NULL);
pthread_join (thread_2, NULL);
}
When running the program, it may print 222 without stop, or be in blocking status after print "222".
I guess the second situiation that the thread_1(func_1) had terminated before calling pthread_mutex_unlock(), making the thread_2 fail to lock the mutex.
I wonder how to solve the problem. It may be pthread_cleanup_push(), right?

C Pthread: Running only 10 threads simultaneously (what is the problem here)

So I'm very new to the whole concept of pthread in C but please hear me out. I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t endCond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t startCond = PTHREAD_COND_INITIALIZER;
void * threadThingy(void * n){
pthread_cond_wait(&startCond, &mutex);
printf("%d: RAND: %d\n", *((int*)n), rand());
//Lock mutex before broadcasting to main thread
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&endCond);
pthread_mutex_unlock(&mutex);
free(n);
fflush(stdout);
return 0;
}
int main(void){
printf("Starting\n");
pthread_t threads[100];
int i = 0;
while(i < 10){
int *arg = malloc(sizeof(int));
*arg = i;
pthread_create(&threads[i], NULL, threadThingy, arg);
i++;
}
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&startCond);
int finished = 0;
while(finished <= 100){
pthread_cond_wait(&endCond, &mutex);
//Lock mutex so no other requests can come in
pthread_mutex_lock(&mutex);
finished++;
int *arg = malloc(sizeof(int));
*arg = 11;
pthread_create(threads[i], NULL, threadThingy, arg);
i++;
pthread_cond_broadcast(&startCond);
pthread_mutex_unlock(&mutex);
}
printf("Stopping\n");
sleep(1000);
}
The whole goal is to run (only) 10 threads simultaneously of the 100. My idea was to start 10 threads, than wait until one is finished and start another one. So I let the program wait until a thread returns, then I start a new one so the thread that just returned gets replaced. What have I missed? Because now I only get this as an output:
Starting
0: RAND: 1804289383
As mentioned by Lavigne958, in function threadThingy() there is deadlock caused by pthread_cond_wait() as it will acquire the lock. Again, you are trying to lock it in next line. This is causing deadlock.
There are a few things need to check:
You need to lock the mutex before calling pthread_cond_wait().
If you solve the above issue, using multiple condition variable with the same mutex may cause further deadlock.
If you are not joining the threads, it will be better to create detached threads using PTHREAD_CREATE_DETACHED attribute.
The problem of N number of threads running simultaneously can be solved with one semaphore OR one condition variable(and one mutex). Example with semaphore is given below.
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
sem_t mysem;
#define NUM_CONCURRENT_THREADS 4
#define MAX_THREADS 40
void *thread(void *arg)
{
printf("Thread id %ld: started\n", pthread_self());
sleep(5); // Do some work
printf("Thread id %ld: Exiting\n", pthread_self());
sem_post(&mysem);
return NULL;
}
int main()
{
pthread_t t[MAX_THREADS];
pthread_attr_t attr;
int rc, i = 0;
sem_init(&mysem, 0, NUM_CONCURRENT_THREADS);
rc = pthread_attr_init(&attr);
rc = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
printf("\nParent begin\n");
while(i < MAX_THREADS)
{
sem_wait(&mysem);
pthread_create(&t[i], &attr, thread, NULL);
i++;
}
printf("\nParent end.\n");
sem_destroy(&mysem);
return 0;
}
Please check blog Tech Easy for more information on threads.
in the function that your threads run, you start by waiting on a condition but you forgot to take the mutex before. So you first must take the mutex before waiting on the condition.
you have what we call a deadlock.
What happens is:
the first thread wakes up (the pthread_con_wait function acquires the lock for you already)
then you try to acquire the lock again => deadlock because you already own the lock so you kinda deadlock yourself.

How to use mutex in C for multithread?

I have 4 processed called A, B, C, D in 4 thread, They printf their name. I want use mutex to process A, B, C, D run in order A, B, C, D. This is my code but it don't work such as me think. How to they work?
#include <stdio.h>
#include <pthread.h>
void processA();
void processB();
void processC();
void processD();
pthread_mutex_t mutex;
void main(){
pthread_t thread1;
pthread_t thread2;
pthread_t thread3;
pthread_t thread4;
pthread_mutex_init(&mutex,NULL);
pthread_create(&thread1, NULL, (void *)&processA,NULL);
pthread_create(&thread2, NULL, (void *)&processB,NULL);
pthread_create(&thread3, NULL, (void *)&processC,NULL);
pthread_create(&thread4, NULL, (void *)&processD,NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_join(thread3, NULL);
pthread_join(thread4, NULL);
pthread_mutex_destroy(&mutex);
}
void processA()
{
while (1)
{
pthread_mutex_lock(&mutex);
printf("A \n");
pthread_mutex_unlock(&mutex);
}
}
void processB()
{
while (1)
{
pthread_mutex_lock(&mutex);
printf("B \n");
pthread_mutex_unlock(&mutex);
}
}
void processC()
{
while (1)
{
pthread_mutex_lock(&mutex);
printf("C \n");
pthread_mutex_unlock(&mutex);
}
}
void processD()
{
pthread_mutex_lock(&mutex);
while (1)
{
pthread_mutex_lock(&mutex);
printf("D \n");
pthread_mutex_unlock(&mutex);
}
}
mutex is for creating mutual exclusion on some context. For example if you have an object that should be reached by one thread at a time, you can use mutex.
You should use 3 semaphores for implementing such feature. You can say:
//semaphore1 = up, semaphore2 = up, semaphore3 = up
//Thread A
//wait for semaphore1 is up
//work
//make semaphore1 down
//Thread B
//wait for semaphore1 is down
//work
//make semaphore2 down
//Thread C
//wait for semaphore2 is down
//work
//make semaphore3 down
//Thread D
//wait for semaphore3 is down
//work
Well this is how you can do it, you just use mutex for the mutual variable (f in this case) and a pthread conditional signal to trigger the action of one thread per second. All of the threads get the signal but only one can access the mutex.
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include <stdlib.h>
#include <memory.h>
#include <stdarg.h>
#include <pthread.h>
pthread_mutex_t v1 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t v2 = PTHREAD_COND_INITIALIZER;
int f = 0;
void *processA(){
while(1){
pthread_mutex_lock(&v1);
pthread_cond_wait(&v2,&v1);
printf("A,%d\n",f);
f++;
pthread_mutex_unlock(&v1);
}
return NULL;
}
void *processB(){
while(1){
pthread_mutex_lock(&v1);
pthread_cond_wait(&v2,&v1);
printf("B,%d\n",f);
f++;
pthread_mutex_unlock(&v1);
}
return NULL;
}
void *processC(){
while(1){
pthread_mutex_lock(&v1);
pthread_cond_wait(&v2,&v1);
printf("C,%d\n",f);
f++;
pthread_mutex_unlock(&v1);
}
void main(){
pthread_t *h;
int i,ptnum = 3;
h = malloc(sizeof(pthread_t)*ptnum);
pthread_create(&h[0],NULL,processA,NULL);
pthread_create(&h[1],NULL,processB,NULL);
pthread_create(&h[2],NULL,processC,NULL);
while(f<=30){
pthread_cond_signal(&v2);
sleep(1);
}
pthread_mutex_lock(&v1);
printf("Main Mutex\n");
for(i=0;i<ptnum;i++){
pthread_join(&h[i],PTHREAD_CANCELED);
}
pthread_mutex_unlock(&v1);
return NULL;
}

Pthread Mutex Segfault

I've never worked with pthreads before and am simply trying to familiarize myself with them. As such, I've written the following test code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int count = 0;
void *increment(void *tex);
int main(int argc, char **argv) {
pthread_t t1, t2, t3;
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
pthread_create(&t1, NULL, &increment, &mutex);
pthread_create(&t2, NULL, &increment, &mutex);
pthread_create(&t2, NULL, &increment, &mutex);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
printf("Value of count is: %d\n", count);
}
void *increment(void *tex) {
pthread_mutex_t *mutex = (pthread_mutex_t *) mutex;
for (int i = 0; i < 100; i++) {
pthread_mutex_lock(mutex);
count++;
pthread_mutex_unlock(mutex);
}
return NULL;
}
I'm compiling the code with GCC using the proper -pthread flag, yet, for whatever reason, any time that any of the threads reach the mutex locking line, segfault. Upon further investigation with GDB, I've discovered that the mutex pointer appears to be invalid inside of the increment function even though I initialized it in main, passed it in as the argument to pthread_create, and have called join on each thread to ensure that main is still in scope. I'm at a loss for why this is happening, and could use some help. Thanks!
You've got:
pthread_mutex_t *mutex = (pthread_mutex_t *) mutex;
what you need is:
pthread_mutex_t *mutex = (pthread_mutex_t *) tex;

why the action is different when pthread_cond_signal in a loop or not in a loop

Today I learn pthread,I write a toy example about the producer and consumer problem.But I find the program's action is different when I put the pthread_cond_signal in a loop or not in a loop.Here is the original code.
#include <pthread.h>
#include <stdio.h>
int good_count = 0;
int total = 0;
pthread_mutex_t mt;
pthread_cond_t cv;
volatile int producer_wait = 1;
void* produce()
{
pthread_mutex_lock(&mt);
printf("Producer Wait;\n");
producer_wait = 1;
pthread_cond_wait(&cv, &mt);
producer_wait = 0;
printf("Received a signal\n");
pthread_mutex_unlock(&mt);
pthread_exit(NULL);
}
void* consume()
{
pthread_mutex_lock(&mt);
while(producer_wait)
{
pthread_cond_signal(&cv);
sleep(1);
}
//pthread_cond_signal(&cv);
pthread_mutex_unlock(&mt);
pthread_exit(NULL);
}
int main()
{
pthread_t threads[2];
pthread_attr_t attr;
/*initialize mutex and cond */
pthread_mutex_init(&mt, NULL);
pthread_cond_init(&cv, NULL);
/*initialize thread attribute*/
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&threads[0], &attr, produce, NULL);
pthread_create(&threads[1], &attr, consume, NULL);
int i;
for (i = 0; i < 2; i++) {
pthread_join(threads[i], NULL);
}
pthread_attr_destroy(&attr);
pthread_mutex_destroy(&mt);
pthread_cond_destroy(&cv);
pthread_exit(NULL);
}
The producer thread block in pthread_cond_wait(&cv, &mt),the consumer thread call pthread_cond_signal(&cv) in a while loop does not take effect.But if I modify the consume() function code like this,then it take effects.
void* consume()
{
pthread_mutex_lock(&mt);
/*while(producer_wait)
{
pthread_cond_signal(&cv);
sleep(1);
}*/
pthread_cond_signal(&cv);
pthread_mutex_unlock(&mt);
pthread_exit(NULL);
}
I am very puzzled, hoping to get answers!
I modify the consume function,move pthread_mutex_lock(&mt) and pthread_mutex_unlock(&mt) into the while loop,and comment the sleep(1), the consumer can release the mutex.In this way,the producer thread can receive the signal. But if I uncomment sleep(1),the producer thread can't receive the signal.Why?
void* consume()
{
while(producer_wait)
{
pthread_mutex_lock(&mt);
pthread_cond_signal(&cv);
//sleep(1);
pthread_mutex_unlock(&mt);
}
pthread_exit(NULL);
}
the consumer thread
with loop, your consumer never releases the mutex, and the producer requires the mutex to continue, so deadlock

Resources