Threads and mutex with broadcast signal [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
In scenario 2 why all threads are not getting triggered?
What is the problem with different mutex variable?
Scenario 1 :
I am creating four threads.Each threads were assigned to different cores all four threads are waiting for signal with same conditional and mutex variable.While passing broadcast signal with same conditional variable all threads were getting triggered.
#define _GNU_SOURCE
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<sched.h>
pthread_cond_t condVar=PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutexVar=PTHREAD_MUTEX_INITIALIZER;
void *thread1(void *ptr)
{
int iVar=1;
printf("Thread %d\n",iVar);
pthread_mutex_lock(&mutexVar);
pthread_cond_wait(&condVar,&mutexVar);
pthread_mutex_unlock(&mutexVar);
printf("Thread %d is unblocked...\n",iVar);
}
void *thread2(void *ptr)
{
int iVar=2;
printf("Thread %d\n",iVar);
pthread_mutex_lock(&mutexVar);
pthread_cond_wait(&condVar,&mutexVar);
pthread_mutex_unlock(&mutexVar);
printf("Thread %d is unblocked...\n",iVar);
}
void *thread3(void *ptr)
{
int iVar=3;
printf("Thread %d\n",iVar);
pthread_mutex_lock(&mutexVar);
pthread_cond_wait(&condVar,&mutexVar);
pthread_mutex_unlock(&mutexVar);
printf("Thread %d is unblocked...\n",iVar);
}
void *thread4(void *ptr)
{
int iVar=4;
printf("Thread %d\n",iVar);
pthread_mutex_lock(&mutexVar);
pthread_cond_wait(&condVar,&mutexVar);
pthread_mutex_unlock(&mutexVar);
printf("Thread %d is unblocked...\n",iVar);
}
int main()
{
int i,j=2;
pthread_t t[4];
cpu_set_t cpuset;
pthread_create(&t[0],0,thread1,0);
pthread_create(&t[1],0,thread2,0);
pthread_create(&t[2],0,thread3,0);
pthread_create(&t[3],0,thread4,0);
for(i=0;i<4;i++) //Assign dedicated core for each thread
{
CPU_ZERO(&cpuset);
CPU_SET(j,&cpuset);
if((pthread_setaffinity_np(t[i],sizeof(cpu_set_t),&cpuset))!=0)
perror("Set_affinity");
j+=2;
}
sleep(5);
pthread_cond_broadcast(&condVar);
while(1);
}
Output:
Thread 1
Thread 4
Thread 2
Thread 3
Thread 1 is unblocked...
Thread 4 is unblocked...
Thread 2 is unblocked...
Thread 3 is unblocked...
Scenario 2:
Instead of same mutex variable I have created different mutex to each thread.While passing broadcast signal among the four,only one thread is getting triggered remaining threads were waiting for signal.
Output for scenario 2 :
Thread 1
Thread 2
Thread 4
Thread 3
Thread 1 is unblocked...

Instead of same mutex variable I have created different mutex to each thread.While passing broadcast signal among the four,only one thread is getting triggered remaining threads were waiting for signal.
That's a misuse of condition variables and undefined behavior. Per the POSIX pthread_cond_wait() documentation:
When a thread waits on a condition variable, having specified a particular mutex to either the pthread_cond_timedwait() or the pthread_cond_wait() operation, a dynamic binding is formed between that mutex and condition variable that remains in effect as long as at least one thread is blocked on the condition variable. During this time, the effect of an attempt by any thread to wait on that condition variable using a different mutex is undefined.

Related

Problem with pthread_cond_wait on multi-core processors

I'm writing a program which receive data from websocket and work with this data in thread pool.
I have problem with pthread_cond_wait when processor have 2 or more cores. After pthread_cond_signal signal is received by all threads which run on different cores. For example if I have 2 cores, then the signal will come to 2 threads at once, which are located on these two cores. If I have single core processor all is good.
What I have to do to get the program to work correctly on multi-core processors? So that only one thread receives the signal to start work.
I wrote an example of my code with generation random text data instead of websocket data.
#include<stdio.h>
#include<stdlib.h>
#include<cstring>
#include<pthread.h>
#include<unistd.h>
pthread_attr_t attrd;
pthread_mutex_t mutexQueue;
pthread_cond_t condQueue;
char textArr[128][24]; //array with random text to work
int tc; //tasks count
int gi; //global array index
void *workThread(void *args){
int ai;//internal index for working array element
while(1){
pthread_mutex_lock(&mutexQueue);
while(tc==0){
pthread_cond_wait(&condQueue,&mutexQueue); //wait for signal if tasks count = 0.
}
ai=gi;
if(gi==127)gi=0;else gi++;
tc--;
pthread_mutex_unlock(&mutexQueue);
printf("%s\r\n",textArr[ai]);
// then work with websocket data
}
}
void *generalThread(void *args){
const char chrs[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; //chars fo random text generation
int ai=0;
srand(time(NULL));
while(1){
for(int i=0;i<23;i++)textArr[ai][i]=chrs[rand()%61];//generating data instead of websocket data
textArr[ai][23]='\0';
tc++;
pthread_cond_signal(&condQueue); //Send signal for thread to begin work with data
if(ai==127)ai=0;else ai++;
}
}
int main(int argc,char *argv[]){
pthread_attr_init(&attrd);
pthread_attr_setdetachstate(&attrd,PTHREAD_CREATE_DETACHED);
pthread_t gt,wt[32];
for(int i=0;i<32;i++)pthread_create(&wt[i],&attrd,&workThread,NULL);
pthread_create(&gt,NULL,&generalThread,NULL);
pthread_join(gt,NULL);
return 0;
}
First some info:
man pthread_cond_wait
Rationale
Some implementations, particularly on a multi-processor, may sometimes cause multiple threads to wake up when the condition variable is signaled simultaneously on different processors.
man pthread_cond_signal
Rationale
Multiple Awakenings by Condition Signal
On a multi-processor, it may be impossible for an implementation of pthread_cond_signal() to avoid the unblocking of more than one thread blocked on a condition variable.
...
The effect is that more than one thread can return from its call to pthread_cond_wait() or pthread_cond_timedwait() as a result of one call to pthread_cond_signal(). This effect is called "spurious wakeup". Note that the situation is self-correcting in that the number of threads that are so awakened is finite; for example, the next thread to call pthread_cond_wait() after the sequence of events above blocks.
So far, so good, the code in your workThread is proper synchronized (but you should put the printf in the synchronized section as well) but the code in your generalThread has no synchronization at all. Encapsulate the code in the while loop with a lock / unlock.
In that case, the first awakened thread has to aquire a lock on the specified mutex, which will be owned by either another thread or the generalThread. Until the mutex is unlocked, the thread blocks (no matter the reason of its wakeup). After the aquisition, it owns the mutex and all other threads will be blocked, the generalThread inclusive.
Note: a pthread_cond_wait implicitly unlocks the specified mutex upon entering the wait state and on a wakeup it tries to aquire a lock on the specified mutex.
Adding a mutex lock to tc++ fully corrects my programs:
void *generalThread(void *args) {
const char chrs[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int ai=0;
srand(time(NULL));
while(1){
for(int i=0;i<23;i++)textArr[ai][i]=chrs[rand()%61];
textArr[ai][23]='\0';
pthread_mutex_lock(&mutexQueue); //this has been added
tc++;
pthread_mutex_unlock(&mutexQueue); //this has been added
pthread_cond_signal(&condQueue);
if(ai==127)ai=0;else ai++;
}
}

Why is another thread, say B running when pthread_mutex is being locked and unlocked inside thread A?

According to the man pages
pthread_mutex_lock locks the given mutex. If the mutex is currently unlocked, it becomes locked and owned by the calling thread, and
pthread_mutex_lock returns immediately. If the mutex is already locked by another thread, pthread_mutex_lock suspends the calling thread
until the mutex is unlocked.
What I understood is when line 3 executes the main thread has ownership of the mtx. It then performs its critcal region actions and then reaches line 4 and unlocks mtx. My question is -
Can the other thread concurrently run when mtx is locked?
What is the use of line 2 since newThread can only unlock mtx when line 4 has been executed, and thus makes line 2 redundant?
What would happen if line 1 is uncommented?
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#include<unistd.h>
sem_t bin_sem;
pthread_mutex_t mtx;
char message[100];
void * thread_function(void * arg)
{
int x;
char message2[10];
while(1)
{
// pthread_mutex_lock(&mtx); //line 1
printf("thread2 : waiting..\n\n");
sem_wait(&bin_sem);
printf("hi i am the new thread waiting inside critical..\n");
scanf("%s",message);
printf("You entered in newthread:%s\n\n",message);
sem_post(&bin_sem);
pthread_mutex_unlock(&mtx); //line 2
}
}
int main(void)
{
pthread_t athread;
pthread_attr_t ta;
char message2[10];
int x;
sem_init(&bin_sem,0,1);
pthread_mutex_init(&mtx,NULL);
pthread_attr_init(&ta);
pthread_attr_setschedpolicy(&ta,SCHED_RR);
pthread_create(&athread,&ta,thread_function,NULL);
while(1)
{
pthread_mutex_lock(&mtx); //line 3
printf("main waiting..\n\n");
sem_wait(&bin_sem);
printf("hi i am the main thread waiting inside critical..\n");
scanf("%s",message);
printf("You entered in main:%s\n\n",message);
sem_post(&bin_sem);
pthread_mutex_unlock(&mtx); //line 4
}
sleep(5);
}
A mutex is a mechanism for implementing critical sections.
Any code between pthread_mutex_lock(x) and pthread_mutex_unlock(x) calls will execute in only one thread at any given time. That's all.
So ...
1. Can the other thread concurrently run when mtx is locked?
If it didn't lock the mtx, then of course.
2. What is the use of line 2 since newThread can only unlock mtx when line 4 has been executed, and thus makes line 2 redundant?
The mutex becomes useless, and you also get UB since you're unlocking it in the thread that didn't lock it:
If the mutex type is PTHREAD_MUTEX_DEFAULT...
Attempting to unlock the mutex if it was not locked by the calling thread results in undefined behavior.
(By default you get mutex type PTHREAD_MUTEX_DEFAULT)
3. What would happen if line 1 is uncommented?
You get thread starvation, since the mutex is locked almost all the time and is immediately re-locked after unlocking (POSIX doesn't guarantee mutex fairness).
A POSIX semaphore does provide fairness in some cases (when you use SCHED_FIFO or SCHED_RR schedulers), but is heavier.
I don't quite understand what you're trying to achieve (the application looks contrived). In a real application there's probably some logical ordering to the actions that either thread needs to take. So if the semaphore works for you, I'd keep it at that and remove the mutex.

Print passed argument to pthread_create [duplicate]

This question already has an answer here:
Unexpected output in a multithreaded program
(1 answer)
Closed 4 years ago.
I want to print the passed to create_thread argument. I create an array with 10 int's to simulate the number of each thread -
void* thr_func(void *arg){
printf("\nTHREAD ID %d", *(int*)arg);
return 0;
}
int main(){
int arr[10]={0,1,2,3,4,5,6,7,8,9};
pthread_t thread_id;
for(int i=0;i<10;i++){
pthread_create(&thread_id, NULL, &thr_func,&arr[i]);
}
return 0;
}
Here is the output from two runs
1:
THREAD ID 1
THREAD ID 5
THREAD ID 6
THREAD ID 2
THREAD ID 3
THREAD ID 4
TTHREAD ID 0
THREAD ID 3
2:
THREAD ID 1
THREAD ID 2
THREAD ID 5
THREAD ID 6
THREAD ID 3
THREAD ID 7
THREAD ID 4
THREAD ID 8
THREAD ID 8
I know I can't rely on consecutive numbers, but why does it print some of them twice ?
As #Some programmer dude mentioned, you should always wait for the termination of your single child threads in your main function (except you detach your threads). The reason why some of your arrayelements are printed twice or more often is because before your buffer is cleared the thread may gets killed. (In your case the thread 8). To avoid that the processes are shut-down before they have finished their work you have to waitfor your threads, or in other words you have to join your threads.
That is done by adding the function: pthread_join(pthread_t thread, void **retvalue);
The pthread_join() function waits for the thread specified by thread to terminate.
Just put it in a separate loopafter your pthread_create() function and the parent thread (main) will wait for his childs.
Edit:
To wait for each thread you could change your pthread_tvariable to an array of threads: pthread_t thread[10] so you could wait for each thread in relation to the index.
int arr[10]={0,1,2,3,4,5,6,7,8,9};
pthread_t thread[10];
for(int i=0;i<10;i++){
pthread_create(&thread[i], NULL, &thr_func,&arr[i]);
}
for(int i=0;i<10;i++){
pthread_join(thread[i],NULL);
}

pthread not working using pthread_cond_signal() and pthread_cond_wait()

I using pthread_cond_wait() and pthread_cond_signal() function to create a multithreaded program. It working correctly if condition correct, but condition incorrect, it not working, it not ignore function printinput(), it stay here, not run continue. Can you help me checking this error?
My code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mutex;
pthread_cond_t cond;
//Read input value
void* readinput(void *arg)
{
pthread_mutex_lock(&mutex);
int a;
printf("Input:");
scanf("%d",&a);
printf("Value: %d\n",a);
/*
if condition correct then "printinput" function
else ignore that function
*/
if (a>=2 && a<=8)
{
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&mutex);
pthread_exit((void *)a);
}
//print input value if condition correctly
void* printinput(void *arg)
{
pthread_mutex_lock(&mutex);
//Block and wait for cond Singal
pthread_cond_wait(&cond,&mutex);
printf("Your value between 2 and 8 \n\n");
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main()
{
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_t th1;
pthread_t th2;
while (1)
{
//Create pthread
pthread_create(&th1,NULL,&printinput,NULL);
pthread_create(&th2,NULL,&readinput,NULL);
//Wait pthread done
pthread_join(th1,NULL);
pthread_join(th2,NULL);
Sleep(1000);
}
}
Result:
Input:5
Value: 5
Your value between 2 and 8
Input:10 Value: 10
pthread_cond_wait() suspends the current thread until the relevant condition is signalled.
For input 5 the first thread signals the condition as it's part of if (a >= 2 && a <= 8) block.
For input 10 the above block is skipped so the condition is never signalled. Therefore the second thread is never woken up and is stuck forever.
Additionally, note there is race condition and I'm actually surprised that the program is often working. In case the first thread locks the mutex, the second thread doesn't enter the mutex section until the first thread function is finished, therefore the condition is signalled before the wait on that condition is invoked. In such situation the second thread would be stuck forever as well.
For the solution working in the way you expect (i.e. consuming true/false from the first thread in the second thread), I'd suggest implementing a queue into which the first thread sends the outputs and the second thread consumes it. It'll fix the race condition too. For the implementation see for example https://stackoverflow.com/a/4577987/4787126

pthread_create() Output [duplicate]

this is my first pthread program, and I have no idea why the printf statement get printed twice in child thread:
int x = 1;
void *func(void *p)
{
x = x + 1;
printf("tid %ld: x is %d\n", pthread_self(), x);
return NULL;
}
int main(void)
{
pthread_t tid;
pthread_create(&tid, NULL, func, NULL);
printf("main thread: %ld\n", pthread_self());
func(NULL);
}
Observed output on my platform (Linux 3.2.0-32-generic #51-Ubuntu SMP x86_64 GNU/Linux):
1.
main thread: 140144423188224
tid 140144423188224: x is 2
2.
main thread: 140144423188224
tid 140144423188224: x is 3
3.
main thread: 139716926285568
tid 139716926285568: x is 2
tid 139716918028032: x is 3
tid 139716918028032: x is 3
4.
main thread: 139923881056000
tid 139923881056000: x is 3
tid 139923872798464tid 139923872798464: x is 2
for 3, two output lines from the child thread
for 4, the same as 3, and even the outputs are interleaved.
Threading generally occurs by time-division multiplexing. It is generally in-efficient for the processor to switch evenly between two threads, as this requires more effort and higher context switching. Typically what you'll find is a thread will execute several times before switching (as is the case with examples 3 and 4. The child thread executes more than once before it is finally terminated (because the main thread exited).
Example 2: I don't know why x is increased by the child thread while there is no output.
Consider this. Main thread executes. it calls the pthread and a new thread is created.The new child thread increments x. Before the child thread is able to complete the printf statement the main thread kicks in. All of a sudden it also increments x. The main thread is however also able to run the printf statement. Suddenly x is now equal to 3.
The main thread now terminates (also causing the child 3 to exit).
This is likely what happened in your case for example 2.
Examples 3 clearly shows that the variable x has been corrupted due to inefficient locking and stack data corruption!!
For more info on what a thread is.
Link 1 - Additional info about threading
Link 2 - Additional info about threading
Also what you'll find is that because you are using the global variable of x, access to this variable is shared amongst the threads. This is bad.. VERY VERY bad as threads accessing the same variable create race conditions and data corruption due to multiple read writes occurring on the same register for the variable x.
It is for this reason that mutexes are used which essentially create a lock whilst variables are being updated to prevent multiple threads attempting to modify the same variable at the same time.
Mutex locks will ensure that x is updated sequentially and not sporadically as in your case.
See this link for more about Pthreads in General and Mutex locking examples.
Pthreads and Mutex variables
Cheers,
Peter
Hmm. your example uses the same "resources" from different threads. One resource is the variable x, the other one is the stdout-file. So you should use mutexes as shown down here. Also a pthread_join at the end waits for the other thread to finish its job. (Usually a good idea would also be to check the return-codes of all these pthread... calls)
#include <pthread.h>
#include <stdio.h>
int x = 1;
pthread_mutex_t mutex;
void *func(void *p)
{
pthread_mutex_lock (&mutex);
x = x + 1;
printf("tid %ld: x is %d\n", pthread_self(), x);
pthread_mutex_unlock (&mutex);
return NULL;
}
int main(void)
{
pthread_mutex_init(&mutex, 0);
pthread_t tid;
pthread_create(&tid, NULL, func, NULL);
pthread_mutex_lock (&mutex);
printf("main thread: %ld\n", pthread_self());
pthread_mutex_unlock (&mutex);
func(NULL);
pthread_join (tid, 0);
}
It looks like the real answer is Michael Burr's comment which references this glibc bug: https://sourceware.org/bugzilla/show_bug.cgi?id=14697
In summary, glibc does not handle the stdio buffers correctly during program exit.

Resources