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.
Related
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().
I have been dealing with a problem in a thread pool for some days now. I tried all types of different things but I can't seem to solve the issue. I have made a simple version that reproduces the problem.
Code:
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
struct bsem_t bsem;
pthread_t threads[2];
/* Binary semaphore */
typedef struct bsem_t {
pthread_mutex_t mutex;
pthread_cond_t cond;
int v;
} bsem_t;
void bsem_post(bsem_t *bsem) {
pthread_mutex_lock(&bsem->mutex);
bsem->v = 1;
pthread_cond_broadcast(&bsem->cond);
pthread_mutex_unlock(&bsem->mutex);
}
void bsem_wait(bsem_t *bsem) {
pthread_mutex_lock(&bsem->mutex);
while (bsem->v != 1) {
pthread_cond_wait(&bsem->cond, &bsem->mutex);
}
bsem->v = 0;
pthread_mutex_unlock(&bsem->mutex);
}
/* Being called by each thread on SIGUSR1 */
void thread_exit(){
printf("%u: pthread_exit()\n", (int)pthread_self());
pthread_exit(NULL);
}
/* Startpoint for each thread */
void thread_do(){
struct sigaction act;
act.sa_handler = thread_exit;
sigaction(SIGUSR1, &act, NULL);
while(1){
bsem_wait(&bsem); // Each thread is blocked here
puts("Passed semaphore");
}
}
/* Main */
int main(){
bsem.v = 0;
pthread_create(&threads[0], NULL, (void *)thread_do, NULL);
pthread_create(&threads[1], NULL, (void *)thread_do, NULL);
pthread_detach(threads[0]);
pthread_detach(threads[1]);
puts("Created threads");
sleep(2);
pthread_kill(threads[0], SIGUSR1);
pthread_kill(threads[1], SIGUSR1);
puts("Killed threads");
sleep(10);
return 0;
}
What the code does, is create two threads. Both threads wait on a binary semaphore (bsem_wait). Then while they are waiting I send a SIGUSR1 signal to both resulting on pthread_exit() being executed on each thread. On my terminal it shows that everything goes as planned..
Output:
Created threads
Killed threads
2695145216: pthread_exit()
2686752512: pthread_exit()
The problem
Although the output seems correct, using pstree shows that only one of two threads die. The other thread stays alive until the whole program exits. Why is this?
Update
Replacing my custom binary semaphore with a normal semaphore seems to solve this for no apparent reason..
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <semaphore.h>
sem_t sem;
pthread_t threads[2];
/* Caller thread will exit */
void thread_exit(){
printf("%u: pthread_exit()\n", (int)pthread_self());
pthread_exit(NULL);
}
/* Startpoint for each thread */
void* thread_do(){
struct sigaction act;
act.sa_handler = thread_exit;
sigaction(SIGUSR1, &act, NULL);
while(1){
sem_wait(&sem); // Each thread is blocked here
puts("Passed semaphore");
}
}
/* Main */
int main(){
sem_init(&sem, 0, 0); // Normal semaphore
pthread_create(&threads[0], NULL, thread_do, NULL);
pthread_create(&threads[1], NULL, thread_do, NULL);
pthread_detach(threads[0]);
pthread_detach(threads[1]);
puts("Created threads in pool");
sleep(2);
//PROBLEM
pthread_kill(threads[0], SIGUSR1);
pthread_kill(threads[1], SIGUSR1);
puts("Destroyed pool");
sleep(10);
return 0;
}
You can't get there from here
pthread_exit() is not listed in the "signal safe funtions" of the signal(7) man page.
rewrite your code to have the pthread_exit call outside of the signal handler.
So the issue seemed to be a deadlock!
The problem is that each thread is waiting inside the bsem_wait of the binary semaphore in different locations:
void bsem_wait(bsem_t *bsem) {
pthread_mutex_lock(&bsem->mutex); // THREAD 2 BLOCKED HERE
while (bsem->v != 1) {
pthread_cond_wait(&bsem->cond, &bsem->mutex); // THREAD 1 WAITING HERE
}
bsem->v = 0;
pthread_mutex_unlock(&bsem->mutex);
}
Thread 1 in this case is the fastest thread. Thread 2 is the slower one. When I run the signal to kill a thread, the waiting thread unblocks and exits as expected. The problem is that it never unlocks the mutex. So the blocked thread (2) remains blocked forever. For some reason, the thread won't be terminated because it is waiting on the mutex.
Just adding an unblock before exiting, solves the issue:
void thread_exit(){
printf("%u: pthread_exit()\n", (int)pthread_self());
pthread_mutex_unlock(&mutex); // NEW CODE
pthread_exit(NULL);
}
This ofcourse is a hack to demonstrate what is happening and shouldn't be used. I am going to follow Jasen's advice and get rid of the signal handler all together and solve it some other way. Namely I have to assure that the thread goes through the whole bsem_wait!
I am working with pthreads right now doing the producer/consumer problem. I am currently just trying to get the producer working and using printf statements to see where my issues are. The problem is the code compiles just fine but when I run it, it doesn't do anything but seems to run just fine. I have tried setting my first line to a printf statement but even that does not print. I have tried using fflush as well and I am running out of ideas. My question why would even the first printf statement get skipped?
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
void *producer();
pthread_mutex_t lock;
pthread_cond_t done, full, empty;
int buffer[10];
int in = 0, out = 0;
int min = 0, max = 0, numOfItems = 0, total = 0;
double avg;
void *producer() {
srand(time(NULL));
int n = rand();
int i;
for(i = 0; i < n; i++)
{
int random = rand();
pthread_mutex_lock(&lock);
buffer[in++] = random;
if(in == 10)
{
pthread_cond_signal(&full);
printf("Buffer full");
pthread_mutex_unlock(&lock);
sleep(1);
}
}
pthread_exit(NULL);
}
void *consumer() {
pthread_exit(NULL);
}
int main(int argc, char *argv[]){
printf("test");
//Create threads and attribute
pthread_t ptid, ctid;
pthread_attr_t attr;
//Initialize conditions and mutex
pthread_cond_init(&full, NULL);
pthread_cond_init(&empty, NULL);
pthread_cond_init(&done, NULL);
pthread_mutex_init(&lock, NULL);
//Create joinable state
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&ptid, &attr,(void *)producer,NULL);
pthread_create(&ctid, &attr,(void *)consumer,NULL);
pthread_join(ptid,NULL);
pthread_join(ctid,NULL);
printf("Program Finished!");
pthread_exit(NULL);
}
man pthread_mutex_init
pthread_mutex_init initializes the mutex object pointed to by mutex
according to the mutex attributes specified in mutexattr. If mutexattr
is NULL, default attributes are used instead.
The LinuxThreads implementation supports only one mutex attributes, the
mutex kind... The kind of a mutex determines whether it can be locked again by
a thread that already owns it. The default kind is fast...
If the mutex is already locked by the calling thread, the behavior of
pthread_mutex_lock depends on the kind of the mutex. If the mutex is of
the fast kind, the calling thread is suspended until the mutex is
unlocked, thus effectively causing the calling thread to deadlock.
That's what happens to your producer: it deadlocks in the call
pthread_mutex_lock(&lock);
- except in the unlikely case n < 2 - thus producing no output.
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
int global;
int i = 30;
int j = 30;
int k = 30;
pthread_mutex_t mutex;
void* child1(void* arg)
{
while(k--)
{
pthread_mutex_lock(&mutex);
global++;
printf("from child1\n");
printf("%d\n",global);
pthread_mutex_unlock(&mutex);
}
}
void* child2(void* arg)
{
while(j--)
{
pthread_mutex_lock(&mutex);
global++;
printf("from child1\n");
printf("%d\n",global);
pthread_mutex_unlock(&mutex);
}
}
int main()
{
pthread_t tid1, tid2;
pthread_mutex_init(&mutex, NULL);
pthread_create(&tid1, NULL, child1, NULL);
pthread_create(&tid2, NULL, child2, NULL);
while(i--)
{
pthread_mutex_lock(&mutex);
global++;
printf("from main\n");
printf("%d\n",global);
pthread_mutex_unlock(&mutex);
}
return 0;
}
I'm new to pthread and multithreading, the result of this code is from main xx and child1 appeared rarely, the three threads never appear together, what's the problem?
Most of time in the critical sections will be spent in the printf calls. You might try:
{
int local;
pthread_mutex_lock(& mutex);
local = ++global;
pthread_mutex_unlock(& mutex);
printf("from <fn>\n%d\n", local);
}
This still doesn't give any guarantee of 'fairness' however, but the printf call is very likely to use a system call or I/O event that will cause the scheduler to kick in.
Your program is similar to the Dining Philosophers Problem in many respects. You don't want any thread to 'starve', but you have contention between threads for the global counter, and you want to enforce an orderly execution.
One suggestion in code replace printf("from child1\n"); to printf("from child2\n"); in void* child2(void* arg) function. And if you want ensure all threads to complete please add the following lines at end of main function.
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
I think you should use 3 differents mutex , by the way use pconditional control in order to avoid having unsafe access
Need help with synchronizing two threads with mutex. Iam new to C and mutexes and Im not sure what to do here. The code has two threads that counts to ten and prints out each number, but is not synch, so it will not print synchronized, it is half synched. Means that i only get trouble in the end, sometimes it prints 8..9..11, 8..9..10..10 and so on.
I cannot make changes to the raw code, if you take away the lines about mutexes, that is the raw code. I can only add lines about mutexes.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t mutex;
int g_ant = 0;
void *writeloop(void *arg) {
while(g_ant < 10) {
pthread_mutex_lock(&mutex);
g_ant++;
usleep(rand()%10);
printf("%d\n", g_ant);
pthread_mutex_unlock(&mutex);
}
exit(0);
}
int main(void)
{
pthread_t tid;
pthread_mutex_init(&mutex, NULL);
pthread_create(&tid, NULL, writeloop, NULL);
writeloop(NULL);
pthread_join(tid, NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
With the condition outside your mutex you may not be receiving the correct values. A guaranteed way to ensure the loop operates in-order would be the following change to writeloop:
void writeloop(void *arg) {
while (g_ant < 10) {
pthread_mutex_lock(&mutex);
if (g_ant >= 10) {
pthread_mutex_unlock(&mutex);
break;
}
g_ant++;
usleep(rand()%10);
printf("%d\n", g_ant);
pthread_mutex_unlock(&mutex);
}
}