I am trying to learn Unix C and doing some exercises for practice. The current problem I am working on involves POSIX threads (mainly pthread_create() and pthread_join())
The problem asks to repeatedly print "Hello World" using two threads. One thread is to print "Hello" 1000 times, while the second thread prints "World" 1000 times. The main program/thread is to wait for the two threads to finish before proceeding.
Here is what I have right now.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
void *print_hello(void *arg)
{
int iCount;
for(iCount = 0; iCount < 1000; iCount++)
{
printf("Hello\n");
}
}
void *print_world(void *arg)
{
int iCount;
for(iCount = 0; iCount < 1000; iCount++)
{
printf("World\n");
}
}
int main(void)
{
/* int status; */
pthread_t thread1;
pthread_t thread2;
pthread_create(&thread1, NULL, print_hello, (void*)0);
pthread_create(&thread2, NULL, print_world, (void*)0);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
This does not seem to work fully. It prints "Hello" as expected. But "World" is not printed at all. Seems like the second thread is not running at all. Not sure I am using pthread_join correctly. My intention is for the main thread to "wait" for these two threads as the exercise asks.
Any help would be appreciated.
What makes you think it isn't running both threads? I think the output is just screaming past you too quickly to notice -- you're going to get a large number of each thread's output in a single block.
Try redirecting the output to a file and reviewing what actually got printed.
I just ran your code.
$ gcc ./foo.c -pthread
$ ./a.out | grep World | wc -l
1000
$ ./a.out | grep Hello | wc -l
1000
Works for me on Ubuntu 10.10 with gcc-4.5.2. Double check your compilation and your output.
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)
Hi fellow programmers,
I wanted to write a simple multi-threaded program in C with pthread, but somehow the pthread_join seems to hang.
It seems happens not always, sometimes everything is running fine, next time it't hanging againg, usually on the first thread.
I already minimized the code to the bare minimum, so that i can exclude other problems. In the full code the threads did some computations, of course. But the problems still persists even with this very reduced code. And on more than one machine, with different OS'es.
strace shows me that the hanging has something to do with a FUTEX_WAIT, the full last lines:
write(1, "Joining Thread 0...\n", 20Joining Thread 0...
) = 20
futex(0x7fff61718a20, FUTEX_WAIT, 1634835878, NULL
I tried to debug it with gdb, but my poor debugging stills are very limited, especially with multi-threaded programs.
I also tried to compile it using different C-standards (C99 and Ansi) and both pthread parameters (-lpthread, -pthread), but the problem still persists.
The (reduced) code monte2.c:
#include <stdio.h>
#include <pthread.h>
void *monte(struct MonteArgs *args) {
pthread_exit(NULL);
}
int main(int argc, char **argv) {
int numThreads, numSamples;
int i;
if (argc != 3) {
printf("Usage: monte threads samples\n");
exit(1);
}
numThreads = atoi(argv[1]);
pthread_t threads[numThreads];
numSamples = atoi(argv[2]);
for (i=0; i<numThreads; i++) {
if (pthread_create(&threads[i], NULL, monte, NULL)) {
printf("Error Creating Thread %d!\n", i);
return 1;
}
}
for (i=0; i<numThreads; i++){
printf("Joining Thread %d...\n", i);
pthread_join(&threads[i], NULL);
}
printf("End!\n");
fflush(stdout);
return(0);
}
I compile with
gcc monte2.c -lpthread -o monte
and run with
./monte2 3 100
where the first argument is the number of threads, and the second is actually not needed for the reduced code.
It's been a while since I've done multi-threaded C, but you shouldn't ignore compiler warnings :-). Compile with -Wall.
You should be seeing a warning like this:
note: expected 'pthread_t' but argument is of type 'pthread_t *'
int WINPTHREAD_API pthread_join(pthread_t t, void **res);
You are passing a pthread_t* when you should be passing pthread_t.
Refer to the pthread_join docs: http://man7.org/linux/man-pages/man3/pthread_join.3.html
This program should be a trivial attempt to run two concurrent threads which both need to write on the same screen.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <ncurses.h>
void *function1(void *arg1);
void *function2(void *arg2);
int main(int argc, char *argv[])
{
printf("hello");
initscr();
printw("screen on\n");
pthread_t function1t;
pthread_t function2t;
if( pthread_create( &function1t, NULL, function1, NULL) < 0)
{
printw("could not create thread 1");
return 1;
}
if( pthread_create( &function2t, NULL, function2, NULL) < 0)
{
printw("could not create thread 2");
return 1;
}
endwin();
return 0;
}
void *function1(void *arg1)
{
printw("Thread 1\n");
while(1);
}
void *function2(void *arg2)
{
printw("Thread 2\n");
while(1);
}
But it doesn't even print hello in the beginning. What's wrong? How can a unique screen be handled in such a program, with two threads?
Update: putting a refresh(); after each printw produces the following output
screen on
Thread 1
Thread 2
$
Where $ is the prompt. So, the program prints the string, but it puts (apparently) randomly some unexpected newlines and it ends. It shouldn’t, due to the while(1) instructions in both the threads!
curses/ncurses in the normal configuration does not support threads, and the recommendation for that has always been to run curses in a single thread. Since ncurses 5.7, there has been rudimentary support for threaded applications if the library is configured (compile-time) to use mutexes and additional entrypoints.
Regarding mutexes, almost any tutorial on POSIX threads covers that. Here is an example: POSIX Threads Programming
It is not printing the hello string but it's quickly cleared with the instruction initscr():
The initscr code determines the terminal type and initializes all
curses data structures. initscr also causes the first call to refresh
to clear the screen. If errors occur, initscr writes an appropriate
error message to standard error and exits; otherwise, a pointer is
returned to stdscr.
printw is printing as expected because you are not refreshing. You should use refresh() after each printw:
printw("screen on\n");
refresh();
int g_ant = 0;
void *writeloop(void *arg)
{
while(g_ant < 10)
{
g_ant++;
usleep(rand()%10);
printf("%d\n", g_ant);
}
exit(0);
}
int main(void)
{
pthread_t time;
pthread_create(&time, NULL, writeloop, NULL);
writeloop(NULL);
pthread_join(time, NUL);
return 0;
}
Hi! I have four questions which I believe goes under the category race condition...? :-)
I'm trying to figure out why the printf of g_ant, on my computer, starts on 2 and continues to 10 in 90% of the cases, with an occasional 1, 3->10 output. My guess is because of the usleep which may hinder thread1 long enough to let thread2 increment and printf before thread1 reaches printf.
Wouldn't this also mess up numbers from 2->10?
I'm also struggeling to understand pthread_join's function in this program. My understanding is that it's used to wait for a thread to complete. Is it waiting for the writeloop function started by pthread_create?
Is writeloop(null) considered second thread?
g_ant++;
isn't atomic operation, which can cause undefined behaviour. You should use
pthread_mutex_lock(&mutex);
and
pthread_mutex_unlock(&mutex);
the reason why it 90% times starts at 2 is because thread time enters the function, increments g_ant and sleeps itself. OS tends to take it away from CPU and put there another thread that is not asleep, in your case that is your main thread which again increments it by 1 runs usleep. Now g_ant has value 2, thread time resumes and prints 2 and increments it to 3. Main thread gets resumed and prints the 3 and again increments it, this keeps switching that's why you see numbers from 2 -> 10 most of the time.
Hopefully it is clear enough and should answer 2. question as well.
pthread_join makes sure that other threads finish their job before your main thread quits the program.
nope it is not considered a second thread, it runs the function on the main thread.
hope it helps.
The main thread is considered another thread. The following might help you understand what's going on before you add mutexes (assuming
you have to do that next). Usually, you don't exit() the whole process
from a thread - it would never be joined in the main thread.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int g_ant = 0;
void *writeloop(void *arg)
{
while(g_ant < 10)
{
g_ant++;
usleep( rand() % 10 );
printf("thread: %u global: %d\n", (unsigned int)pthread_self(), g_ant);
}
return NULL;
}
int main(void)
{
pthread_t t;
pthread_create(&t, NULL, writeloop, NULL);
writeloop(NULL);
pthread_join(t, NULL);
printf("Joined\n");
return 0;
}
I'm sure I'm missing something basic, but I'm writing a program that fork()s several child processes, each of which create several pthreads. It seems that the pthread_create call never works from a child process. Here is sample code to explain what I mean:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
// Listen for a request from user proc i
void *wait_for_req(void *cvoid) {
int req;
int read_ret;
printf("new thread started\n");
pthread_exit(NULL);
}
void spawn_read_threads(int proc_num, int n) {
int i;
printf("About to spawn %d read threads\n", n);
for (i=0; i<n; i++) {
pthread_t *t;
printf("spawning new thread\n");
int create_result = pthread_create(t, NULL, wait_for_req, NULL);
printf("_create returned %d\n", create_result);
pthread_join(*t, NULL);
}
}
int main() {
if (!fork())
spawn_read_threads(0, 1);
}
The output of this program is
About to spawn 1 read threads
spawning new thread
But if I comment out if comment out if (!fork()):
About to spawn 1 read threads
spawning new thread
_create returned 0
new thread started
So why doesn't execution get through create_result in the first case?
And if this is useful:
rob#ubuntu:/mnt/hgfs/Virtual Machines$ uname -a
Linux ubuntu 2.6.32-24-generic #42-Ubuntu SMP Fri Aug 20 14:24:04 UTC 2010 i686 GNU/Linux
I can see one immediate problem with your code: pthread_create takes the address of an existing pthread_t variable and stores the new thread ID in it. You're passing an uninitialized pointer instead. You need to do something like:
pthread_t tid;
int create_result = pthread_create(&tid, NULL, wait_for_req, NULL);
I'd say you were just lucky when it worked once, because your current code essentially causes undefined behaviour.
Besides the errors you found in your answer, you are not supposed to call pthread_* from within the forked process. After, fork() only async-signal safe functions should be used. You must exec() first, and then you may create some pthreads.
pthread_t t;
printf("spawning new thread\n");
int create_result = pthread_create(&t, NULL, wait_for_req, NULL);
printf("_create returned %d\n", create_result);
pthread_join(t, NULL);