#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.
Related
I'm fairly new to threads in C. For this program I need to declare a thread which I pass in a for loop thats meant to print out the printfs from the thread.
I can't seem to get it to print in correct order. Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 16
void *thread(void *thread_id) {
int id = *((int *) thread_id);
printf("Hello from thread %d\n", id);
return NULL;
}
int main() {
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
int code = pthread_create(&threads[i], NULL, thread, &i);
if (code != 0) {
fprintf(stderr, "pthread_create failed!\n");
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
//gcc -o main main.c -lpthread
That's the classic example of understanding multi-threading.
The threads are running concurrently, scheduled by OS scheduler.
There is no such thing as "correct order" when we are talking about running in parallel.
Also, there is such thing as buffers flushing for stdout output. Means, when you "printf" something, it is not promised it will happen immediately, but after reaching some buffer limit/timeout.
Also, if you want to do the work in the "correct order", means wait until the first thread finishes it's work before staring next one, consider using "join":
http://man7.org/linux/man-pages/man3/pthread_join.3.html
UPD:
passing pointer to thread_id is also incorrect in this case, as a thread may print id that doesn't belong to him (thanks Kevin)
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.
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.
I am trying to run a simple multi threaded programming and i am getting this error from gcc
return code from pthread_create() is 11
how do i solve this issue ?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 20000
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
Well, you could start with determining what the error actually means. According to this and this (other resources will tell you the same information, this is just an example), the number 11 stands for EAGAIN which in turn means "The system lacked the necessary resources to create another thread, or the system-imposed limit on the total number of threads in a process PTHREAD_THREADS_MAX would be exceeded.".
That matches the fact that your are trying to create 20.000(!) threads. Create less threads, or wait until threads complete before starting new ones.
Note that the maximum number of threads that can be created depends on your system (and possibly even depends on a number of other settings). Google for "How to Find PTHREAD_THREADS_MAX" if you really need to know.
However, unless this is just a trivial example for toying around (or maybe even then) you might want to look into the concept of thread pools and queues.
The following code is a simple thread game, that switches between threads causing the timer to decrease.
It works fine for 3 threads, causes and Abort(core dumped) for 4 threads, and causes a seg fault for 5 or more threads.
Anyone have any idea why this might be happening?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <assert.h>
int volatile num_of_threads;
int volatile time_per_round;
int volatile time_left;
int volatile turn_id;
int volatile thread_running;
int volatile can_check;
void * player (void * id_in){
int id= (int)id_in;
while(1){
if(can_check){
if (time_left<=0){
break;
}
can_check=0;
if(thread_running){
if(turn_id==id-1){
turn_id=random()%num_of_threads;
time_left--;
}
}
can_check=1;
}
}
pthread_exit(NULL);
}
int main(int argc, char *args[]){
int i;
int buffer;
pthread_t * threads =(pthread_t *)malloc(num_of_threads*sizeof(pthread_t));
thread_running=0;
num_of_threads=atoi(args[1]);
can_check=0;
time_per_round = atoi(args[2]);
time_left=time_per_round;
srandom(time(NULL));
//Create Threads
for (i=0;i<num_of_threads;i++){
do{
buffer=pthread_create(&threads[i],NULL,player,(void *)(i+1));
}while(buffer == EAGAIN);
}
can_check=1;
time_left=time_per_round;
turn_id=random()%num_of_threads;
thread_running=1;
for (i=0;i<num_of_threads;i++){
assert(!pthread_join(threads[i], NULL));
}
return 0;
}
See below on why you should not depend on volatile in pthreads. However, your specific problem is probably because you malloc your pthread array, based on the num_of_threads variable before you've actually set num_of_thread from argv[]:
pthread_t *threads = (pthread_t *)malloc (num_of_threads * sizeof (pthread_t));
thread_running = 0;
num_of_threads = atoi (args[1]);
So there's a very good chance you're writing beyond the end of the threads array. The num_of_threads variable will probably be zero on start-up which means you're not allocating what you think you are. Move the allocation to after the extraction of the arguments and that should fix it.
And now, for your viewing pleasure :-), my original rant on the unsafe use of volatile, which I still stand by.
Do not rely on volatile to protect your shared variables. The correct way to do this is with the pthread_mutex_blab_blah_blah calls.
Of particular note, examine this code segment:
if (can_check) {
if (time_left <= 0) {
break;
}
// URK!!
can_check=0;
URK!! is the point where your current thread may be switched out and another run, leading to the possibility that two threads can be running a critical section of code.
My advice is to forget the can_check altogether and just protect all the shared variables with a mutex, something like (from memory):
void *player (void * id_in) {
int id = (int)id_in;
while (1) {
pthread_mutex_lock (&mutex);
if (time_left <= 0) {
pthread_mutex_unlock (&mutex);
break;
}
if (thread_running) {
if (turn_id == id-1) {
turn_id = random() % num_of_threads;
time_left--;
}
}
pthread_mutex_unlock (&mutex);
}
pthread_exit(NULL);
}
Then put at file-level:
pthread_mutexattr_t mutexattr; // prob. not needed at file level.
pthread_mutex_t mutex;
and, in main, before starting any other threads:
pthread_mutexattr_init (&mutexattr);
// Change attributes if needed.
pthread_mutex_init (&mutex, &mutex_attr);
// Then run all you other stuff here, make sure you've joined with all threads.
pthread_mutex_destroy (&mutex);
Oh yeah, although I haven't done it, you should also check the return codes for all those mutex calls. I'm not going to add that since it'll clog up the answer with unnecessary detail, but it's good practice.