I have been writing test programs regarding thread synchronization for a larger project for school. One of the test programs I wrote was a short snippet of code to test the "semaphore.h" library. The code is as follows:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
//Semaphore
sem_t mutex;
//Critical section variable
int crit;
//Method for pthreads
void* method()
{
int x;
//Loop to increment 'crit'
for (x = 0; x < 5000000; x++)
{
sem_wait(&mutex);
//Critical Section
crit++;
sem_post(&mutex);
}
pthread_exit(0);
}
int main()
{
pthread_t t1, t2;
sem_init(&mutex, 0, 1);
pthread_create(&t1, NULL, method, NULL);
pthread_create(&t2, NULL, method, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
sem_destroy(&mutex);
//This value should be '10000000'
printf("Value of 'crit': %d\n", crit);
return 0;
}
The final value of the 'crit' variable should be ten-million, but I am only getting numbers close to it, indicating a race condition. I have compared my code to other samples, and it looks right, but I keep getting the same problem. Any thoughts?
Your critical section is not locked at all, which hypothesis fits your symptoms well.
sem_init() is failing with ENOSYS. sem_wait() and sem_post() subsequently fail with EINVAL, and sem_destroy() fails as well (probably again with ENOSYS). Your worker threads are stepping on each other's increments.
Are you on OS X? That's the most common platform at present that does not support unnamed POSIX semaphores. Try the named semaphore interface, defined in the same header file, which is supported.
Related
When we detach a thread, it is not associated with calling thread anymore then why did the join call succeed with return value 0??
// C program to show thread functions
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
void* func(void* arg)
{
int x = pthread_detach(pthread_self());
printf("x = %d\n", x);
printf("Error description is : %s\n",strerror(x));
printf("Inside the thread\n");
pthread_exit(NULL);
}
void fun()
{
pthread_t ptid;
pthread_create(&ptid, NULL, &func, NULL);
int x = pthread_join(ptid, NULL);
printf("Error description is : %s\n",strerror(x));
pthread_exit(NULL);
}
int main()
{
fun();
return 0;
}
Output -
x = 0
Error description is : Success
Inside the thread
Error description is : Success
as you can see from above code, pthread_join returned success on an already detached thread.
I can reproduce the behavior you describe with your program, using glibc 2.28 and gcc 8.5.0.
This variation produces behavior more in line with what I think you expected:
// C program to show thread functions
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <semaphore.h>
sem_t sem;
void *func(void *arg) {
int x = pthread_detach(pthread_self());
sem_post(&sem);
printf("x = %d\n", x);
printf("Error description in second thread is : %s\n",strerror(x));
printf("Inside the thread\n");
pthread_exit(NULL);
}
void fun() {
pthread_t ptid;
pthread_create(&ptid, NULL, &func, NULL);
sem_wait(&sem);
int x = pthread_join(ptid, NULL);
printf("Error description in initial thread is: %s\n",strerror(x));
pthread_exit(NULL);
}
int main() {
sem_init(&sem, 0, 0);
fun();
return 0;
}
I modified the output a bit, but the main difference is that in this version, the initial thread waits to attempt to join the second one until the second signals via a semaphore that it has detached itself. This is the output I get:
x = 0
Error description in second thread is : Success
Inside the thread
Error description in initial thread is: Invalid argument
In this program, then, the pthread_join() call returns EINVAL, consistent with the target thread not being joinable.
This seems to reflect a race condition. Apparently, in the implementation I am testing and probably in yours as well, if pthread_join() proceeds far enough before the target thread detaches itself, then it waits for the target thread to terminate, even though eventually that thread is detached.
Note, however, that it is erroneous in the first place to attempt to both join and detach the same thread. POSIX makes only recommendations for the behavior in such case, while leaving it formally undefined (as far as POSIX is concerned). Glibc's pthread_join will detect the case where the target thread is already detached and fail with EINVAL, but the documentation doesn't say anything about what happens if a thread is detached while another one is trying to join it. Erroneous behavior does not necessarily produce predictable results.
#include <stdio.h>
#include <pthread.h>
#include <semaphore>
sem_t empty, full, mutex;
#define N 10
void* producerThread(void*) {
int i = 0;
while (1) {
sem_wait(&empty);
sem_wait(&mutex);
buff[i] = rand();
i = ++i % N;
sem_post(&mutex);
sem_post(&full);
}
}
void* consumerThread(void*) {
int i = 0;
while (1) {
sem_wait(&full);
sem_wait(&mutex);
printf("%d\n", buff[i]);
i = ++i % N;
sem_post(&mutex);
sem_post(&empty);
}
}
void main() {
pthread_t producer, consumer;
sem_init(&empty, N);
sem_init(&full, 0);
sem_init(&mutex, 1);
pthread_create(&producer, NULL, &producerThread, NULL);
pthread_create(&consumer, NULL, &consumerThread, NULL);
pthread_join(producer, NULL);
pthread_join(consumer, NULL);
sem_destroy(&empty);
sem_destroy(&full);
sem_destroy(&mutex);
}
I have the following question, this code is well know Producer-Consumer problem when learning about multi-threading, but i do not understand why do we need an additional semaphore (mutex) in this case? Can't we do everything with semaphores full & empty and there will be no problems whatsoever where producer produces on the spot consumer didnt already consume or vice-versa? Afaik with mutex we are adding additional bagage on the code and this is not necessary. Can someone point to me why we need 3 semaphores instead of 2?
I've tried running this code on my computer and everything works the same with and without additional semaphore, so I do not understand why did author choose 3 semaphores in this instance?
The empty and full semaphores take values in the range [0..N), allowing the producer to run ahead of the consumer by up to N elements.
The mutex semaphore only bounces between values 0 and 1, and enforces a critical section ensuring that only one thread is touching any part of the buffer memory at a time. However, the separate computation of i on each thread and the empty/full handshake ensures there can be no data race on individual elements of buff, so that critical section is probably overkill.
You don't show the definition of buff. For a sufficiently narrow datatype (like individual bytes), some architectures may exhibit word tearing on concurrent writes to adjacent elements. However in your example only one thread is performing writes, so even in the presence of word-tearing the concurrent adjacent reads are unlikely to observe a problem.
Value of Global variable var in main() function sometimes comes -1 and sometimes 1 .How to write a robust code without using sleep function so that thread get time to get started and running .
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int var = -1; // GLobal Variable
void *myThreadFun(void *vargp)
{
var = 1;
return NULL;
}
int main()
{
pthread_t thread_id;
printf("Before Thread\n");
pthread_create(&thread_id, NULL, myThreadFun, NULL);
printf("var=%d",var);
pthread_join(thread_id, NULL);
printf("After Thread\n");
exit(0);
}
Value of Global variable var in main() function sometimes comes -1 and
sometimes 1 .How to write a robust code without using sleep function
so that thread get time to get started and running .
It is a distressingly common misconception among those new to multithreaded programming that problems such as yours are a matter of timing. That is not the case, at least not from the perspective of the threading and memory models of most modern high-level programming languages. No amount of delay alone ensures that one thread will see the effects on memory produced by another, therefore robust code does not use timing functions such as sleep() for that purpose.
Rather, the issue is one of synchronization. This is the area that contains rules about what writes to memory by one thread must be visible to other threads. It also covers special kinds of objects and functions that serve to enable threads to affect the execution of other threads, generally by temporarily blocking them from proceeding. These two facets are closely linked.
The pthread_create() and pthread_join() functions have synchronization effects. Among other things, all writes to memory by a thread T1 before it calls pthread_create() to start a thread T2 are visible to T2 (modulo subsequent rewrites of the same memory). All writes to memory by T2 are visible to T1 after it successfully joins T2 via pthread_join(). Therefore, one solution to the question as posed is to wait until after joining the second thread before attempting to read var, as #Robert's answer suggests.
If that is undesirable, then you'll need to engage some other kind of synchronization mechanism to make the main thread wait for the second to update var. Such a wait on a synchronization object will also have the effect of making the second thread's write visible to the main thread.
The most general-purpose synchronization technique offered by pthreads is the condition variable which must be used in conjunction with a mutex. You will find many explanations here on SO and elsewhere about how properly to use a CV.
For your particular case, however, you might find a semaphore easier to set up and use. Semaphores are technically separate from the pthreads library proper, but they have suitable synchronization semantics, both for making threads wait and for making memory operations of one thread visible to another. That might look like this:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
int var = -1; // GLobal Variable
sem_t semaphore;
void *myThreadFun(void *vargp)
{
var = 1;
// increment the semaphore's value
sem_post(&semaphore);
return NULL;
}
int main()
{
pthread_t thread_id;
// initialize the semaphore with value 0
sem_init(&semaphore, 0, 0);
printf("Before Thread\n");
pthread_create(&thread_id, NULL, myThreadFun, NULL);
// Wait until the semaphore's value can be decremented by one without
// it becoming negative (and then perform the decrement before proceeding).
sem_wait(&semaphore);
printf("var=%d",var);
pthread_join(thread_id, NULL);
printf("After Thread\n");
exit(0);
}
I think your code is robust, it's just where you print the result which is incorrect. You need to ensure your thread has finished his work before printing the result.
If you print the result before calling pthread_join, there are two possibilities:
myThreadFun has already changed var, in such case var will contain the value 1
myThreadFun hasn't been completely executed, in such case, var will have its initial value -1.
If you print the result after calling pthread_join, the function myThreadFun will be fully executed and it will print 1.
int main()
{
pthread_t thread_id;
printf("Before Thread\n");
pthread_create(&thread_id, NULL, myThreadFun, NULL);
pthread_join(thread_id, NULL);
printf("After Thread\n");
printf("var=%d",var); /* Here, the thread has completed */
exit(0);
}
Robert's solution is sensible, but I believe you don't actually want to wait for the thread to complete.
If you want the main thread to wait for the variable to be set by the thread without waiting for the thread to end, you will need some kind of synchronization. I'll use a semaphore, but there are a number of other solutions.
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
#include <stdlib.h>
#include <unistd.h>
static sem_t started_threads_sem;
static int var;
static void *myThreadFun(void *vargp) {
sleep(3); // This is the thread doing some initialization.
var = 1;
sem_post(&started_threads_sem);
sleep(3); // This is the thread doing stuff.
return NULL;
}
int main() {
printf("Before Thread\n");
sem_init(&started_threads_sem, 0, 0);
pthread_t thread_id;
pthread_create(&thread_id, NULL, myThreadFun, NULL);
// Wait for the thread to have started.
sem_wait(&started_threads_sem);
printf("var=%d\n", var);
pthread_join(thread_id, NULL);
printf("After Thread\n");
exit(0);
}
Before Thread
<3 s pause>
var=1
<3 s pause>
After Thread
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
int count = 0;
pthread_mutex_t MUTEX = PTHREAD_MUTEX_INITIALIZER;
void* func1(void* a){
pthread_mutex_lock(&MUTEX);
for(;count < 4;count++){
printf("LOOP 1: %d\n",count);
sleep(1);
}
pthread_mutex_unlock(&MUTEX);
}
void* func2(void* a){
pthread_mutex_lock(&MUTEX);
for(;count < 8;count++){
printf("LOOP 2: %d\n",count);
sleep(1);
}
pthread_mutex_unlock(&MUTEX);
}
int main(){
pthread_t tid[2];
int a = 1;
int status;
if(pthread_create(tid,NULL,func1,(void*)&a))
printf("func1 error\n");
if(pthread_create(tid+1,NULL,func2,(void*)&a))
printf("func2 error\n");
//pthread_join(*tid, (void *) &status);
//pthread_join(*(tid+1), (void *) &status);
}
simple code for testing how thread and mutex works.
If I run the code, it just terminates without showing anything (sometimes just one line "LOOP 1: 0")
If I uncomment
//pthread_join(*tid, (void *) &status);
//pthread_join(*(tid+1), (void *) &status);
then it works well.
HOW this happens? someone please explain
pthread_join(t,...) waits until the thread t is finished. That is to say, the ...join call does not return until t is finished.
So, your question really is about what happens in a C program if the main() function returns while threads that were created by pthread_create(...) still are running.
The answer (at least, for some versions of C)* is that after main() returns some value, v, the library then calls exit(v). You can look in the man pages or, in the documentation for whatever system you're running on to find out what else exit(...) does, but one of the things that it does is, it terminates the entire process, including all of its threads.
* I am not 100% certain that every version of C and the C standard libraries behave in this way, but it's the behavior that I am accustomed to expect.
Note also that this behavior is different from modern C++ where, std::thread instances can continue to run even after main(...) has returned.
Firstly, I'm Italian and sorry for my bad English.
Anyway, I should do this exercise:
"Write in C a programm which generate a thread. The main shows odd number from 1 to 9, the thread shows even number from 2 to 10. Synchronize the main and the thread with semaphores"
I have written the pseudocode in this way:
//semaphores
semParent = free
semChild = busy
main
generate thread "child"
for i=1 to 9 step 2
P(semParent)
print i
V(semChild)
end for
end main
child
for i=2 to 10 step 2
P(semChild)
print i
V(semParent)
end child
And this is how I have implemented in C:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t semParent;
pthread_mutex_t semChild = PTHREAD_MUTEX_INITIALIZER;
void* functionChild (void* arg) {
for(int i=2; i<=10; i+=2) {
pthread_mutex_lock(&semChild);
printf("CHILD: %d\n",i);
pthread_mutex_unlock(&semParent);
}
return NULL;
}
int main(void) {
pthread_t child;
pthread_create(&child, NULL, &functionChild, NULL);
pthread_mutex_init(&semParent, NULL);
for(int i=1; i<=9; i+=2) {
pthread_mutex_lock(&semParent);
printf("PARENT : %d\n",i);
pthread_mutex_unlock(&semChild);
}
pthread_join(child, NULL);
}
But the output is always different whenever I run the program.
What's wrong?
I use CygWin64 Terminal in Windows 10 64 bit.
Thanks in advance.
A pthread_mutex_t is not a semaphore (though a semaphore can be used as a mutex if you do a "V" to initialize it to "free"). The semaphore API is sem_init, sem_post and sem_wait.
By using pthread_mutex_unlock on a mutex that was locked by another thread, your program is triggering undefined behavior.
This may not be the cause of the problem you are experiencing now, but you should never use printf() in a multithreaded program. printf() writes to a buffer and doesn't always print to the screen right away. Instead you should use sprintf() and write:
char buff[20];
sprintf("PARENT: %d\n", i);
write(1, buff, strlen(buff));
I think that pthread_mutex_init(&semParent, NULL) with NULL attributes and PTHREAD_MUTEX_INITIALIZER have the same effect, which is both locks are initialised to unlocked. Your problem though does not have a critical section with the strict meaning. So a better solution whould be condition variables as #Serhio mentioned. You can also check out semaphores http://www.csc.villanova.edu/~mdamian/threads/posixsem.html which give bigger freedom and can also have the functionality of mutexes.