//trying to make each thread print its thread number not id and then print a message from the array would like to be able to pass array in pthread create but right now I am getting a an error array subscript is not an integer please help me
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
void * print_funtion( void* i, void* message)
{
printf("Thread %d: ",(int*) i);
printf("Thread %s: ", message);
return NULL;
}
int main(int argc, char* argv[]){
int i;
int num = atoi(argv[1]);
//printf("%d \n", num);
for(i = 1; i <= num; i++)
{
char *messages[] = {"Hello", "Bonjour", "Hola", "Shalom", "Namaste", "Gutan Tag", "God dag","Ola", "Salut", "Napot", "Dia"};
//printf("%d \n", i);
pthread_t tid;
pthread_create(&tid, NULL, print_funtion,(void*)i, (void*)messages[i]);
pthread_join(tid,NULL);
}
return 0;
}
There are many problems in the code and I'll point them out individually as comments:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
// Note: In most cases, you should use (char *) for strings instead of char[XX].
// Note: You don't need to set the number of elements in the array
// because it is automatically inferred from the initializer.
char *messages[] = {"Hello", "Bonjour", "Hola", "Shalom", "Namaste", "Gutan Tag", "God dag","Ola", "Salut", "Napot", "Dia"};
void *print_function(void *data)
{
// The data you passed is int not a pointer to int.
int i = (int)data;
printf("Thread %d: \n", i);
// You need to use %s for printing string.
printf("Message: %s\n", messages[i]);
return NULL;
}
int main(int argc, char* argv[])
{
int i;
int num = atoi(argv[1]);
// Limit the number of running threads so you don't slow down you computer (10 is already too much. It depends on the number of cores you CPU has).
#define MAX_NUM_OF_THREADS 10
if(num > MAX_NUM_OF_THREADS)
num = MAX_NUM_OF_THREADS;
// I explain why we need to store the thread ids down below.
pthread_t thread_ids[MAX_NUM_OF_THREADS];
for(i = 0; i < num; i++)
{
pthread_t tid;
void *thread_data = (void *)(i + 1);
pthread_create(&tid, NULL, print_function, thread_data);
thread_ids[i] = tid;
}
// You can't join with the thread in the previous loop because it will serialize thread creation.
// Meaning the program will not create the next thread before the current thread finish execution.
// Instead, you need to create all the threads first then you join to them one by one afterward.
// And for that you need to store the thread ids for each thread in order to join with them after they are created.
for(i = 0; i < num; i++)
{
pthread_join(thread_ids[i], NULL);
}
return 0;
}
Related
Here is what I need to do:
Write a pthread program that takes an integer command line argument n,
spawns n threads that will each generate a random numbers between -100
and 100, and then computes and prints out the sum of these random
numbers. Each thread needs to print out the random number it
generates.
Here is what I have:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
int randomNum=0;
int randomSum=0;
void *randomNumberGenerator(void *id){
int *myid = (int *)id;
randomNum = rand()% 201 + (-100);
printf("%d\n", randomNum);
randomSum+=randomNum;
}
int main (int argc , char *argv[]){
int command;
char *strNumThreads = NULL;
int i;
while((command = getopt(argc, argv, "n:"))!=-1){
if(command == 'n'){
strNumThreads = optarg;
break;
}
}
int numThreads = atoi(strNumThreads);
pthread_t thread;
int newThread;
for(i = 0; i<numThreads; i++){
srand(time(NULL));
pthread_create(&thread, NULL, randomNumberGenerator, (void*)i);
}
pthread_exit(NULL);
printf("%d\n" , randomSum);
return 0;
}
For some reason randomSum is not getting printed.
randomNum is a variable that is shared among all threads, so you need a mutex
when you access the variable, because randomSum+=randomNum; is not an atomic
operation. The current process might get interrupted and another process is
scheduled which changes both variables. When the interrupted process resumes, it
will overwrite randomNum and you end up with garbage.
Also you have to wait for all threads to finish until you print the sum. For
that you have to execute pthread_wait.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
// can be a global variable
int randomSum=0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *randomNumberGenerator(void *id){
int randomNum=0; // does not need to be a global variable
randomNum = rand()% 201 + (-100);
printf("%d\n", randomNum);
pthread_mutex_lock(&mutex);
randomSum+=randomNum;
pthread_mutex_unlock(&mutex);
pthread_exit(0);
}
int main (int argc , char *argv[]){
int command;
char *strNumThreads = NULL;
int i;
while((command = getopt(argc, argv, "n:"))!=-1){
if(command == 'n'){
strNumThreads = optarg;
break;
}
}
// initializing the randomizer
srand(time(NULL));
int numThreads = atoi(strNumThreads);
if(numThreads == 0)
{
fprintf(stderr, "Invalid number of threads\n");
return 1;
}
pthread_t threads[numThreads];
for(i = 0; i<numThreads; i++){
pthread_create(threads + i, NULL, randomNumberGenerator, NULL);
}
for(i = 0; i < numThreads; ++i)
pthread_join(threads[i], NULL);
printf("%d\n" , randomSum);
return 0;
}
You really need to learn how to use the libraries you are using. pthread_exit
must be used by the threads to tell the system "I'm finished", calling it in the
main thread makes no sense.
pthread_create(&thread, NULL, randomNumberGenerator, (void*)i);
I consider this an uggly hack, what you should do is create an array with the
ids of the threads and pass every thread a pointer to its id, like this:
int ids[numThreads];
for(i = 0; i<numThreads; i++){
ids[i] = i;
pthread_create(&thread, NULL, randomNumberGenerator, ids+i);
}
and in the thread you can do
void *randomNumberGenerator(void *idp) {
int *id = idp;
printf("My thread id is %d\n", *id);
...
pthread_exit(NULL);
}
And if your worker threads are just calculating a value, you can use
pthread_exit to return that value back to the main thread. For example:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
struct thdata {
int id;
int random;
};
void *randomNumberGenerator(void *data) {
struct thdata *ret = data;
ret->random = rand()% 201 + (-100);
printf("thread with id %d: random %d\n", ret->id, ret->random);
pthread_exit(data);
}
int main (int argc , char *argv[]){
int i;
// initializing the randomizer
srand(time(NULL));
int numThreads = 5;
if(numThreads == 0)
{
fprintf(stderr, "Invalid number of threads\n");
return 1;
}
pthread_t threads[numThreads];
struct thdata data[numThreads];
for(i = 0; i<numThreads; i++){
data[i].id = i;
pthread_create(threads + i, NULL, randomNumberGenerator, data+i);
}
int randomSum = 0;
for(i = 0; i < numThreads; ++i)
{
struct thdata *data;
pthread_join(threads[i], (void**) &data);
randomSum += data->random;
}
printf("The sum of the random values is: %d\n" , randomSum);
return 0;
}
Which gives me the output (for 5 threads):
thread with id 0: random 72
thread with id 4: random -94
thread with id 1: random 1
thread with id 2: random -74
thread with id 3: random 42
The sum of the random values is: -53
You currently have a data race in place, because you have multiple threads accessing randomSum concurrently. Here's a solution, with comments, using Mutexes to solve the problem.
Note how using a struct to hold the sum and it's mutex allows us to get rid of all globals.
As a plus, I replaced your random generator with a proper one on POSIX systems. Note that your multiple calls to srand() are wrong, and cause less randomicity. You should only ever call srand() once, to generate the seed.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
#include <pthread.h>
static bool HAS_URANDOM = true; // Global
unsigned int random_uint() {
unsigned int r_uint;
// Try to open the random generator device
FILE *f = fopen("/dev/urandom", "r");
if (f == NULL) {
if (HAS_URANDOM) {
// Warn that urandom isn't working, but fallthrough to rand()
printf("---- Failed loading random generator device /dev/urandom. Defaulting to rand().\n");
srand((unsigned int) time(NULL));
HAS_URANDOM = false;
}
r_uint = (unsigned int) rand();
} else {
// If we have urandom, just read from it and cast to uint
fread(&r_uint, sizeof(r_uint), 1, f);
fclose(f);
}
return r_uint;
}
// Inclusive range
// https://stackoverflow.com/a/17554531/2080712
unsigned int generate_uint(unsigned int lower, unsigned int upper) {
if (upper - lower == UINT_MAX) {
fprintf(stderr, "Invalid bounds on generate_int().\n");
exit(EXIT_FAILURE);
}
unsigned int r_uint;
const unsigned int range = 1 + (upper - lower);
if (range == 0) {
fprintf(stderr, "Invalid range!\n---- upper=%d\n---- lower=%d\n---- range=%d\n", upper, lower, range);
exit(EXIT_FAILURE);
}
const unsigned int buckets = UINT_MAX / range;
const unsigned int limit = buckets * range;
/* Create equal size buckets all in a row, then fire randomly towards
* the buckets until you land in one of them. All buckets are equally
* likely. If you land off the end of the line of buckets, try again. */
do {
r_uint = random_uint();
} while (r_uint >= limit);
unsigned int res = lower + (r_uint / buckets);
return res;
}
typedef struct {
pthread_mutex_t lock; // Our lock to avoid data races
long sum; // The sum value
} sum_t;
// Thread function
void *do_sum(void *arg) {
sum_t *sum = (sum_t*)(arg); // Reinterpret the argument as sum_t
int val = generate_uint(0, 100) - 100; // Generate an integer in the range we want
pthread_mutex_lock(&sum->lock); // Lock the value
sum->sum += val; // Sum
pthread_mutex_unlock(&sum->lock); // Unlock the value
return NULL;
}
int main(int argc, char *argv[]) {
// Guarantee argument
if(argc != 2) {
printf("Please provide a number of threads.\n");
exit(EXIT_FAILURE);
}
// Get our thread count
long count = strtol(argv[1], NULL, 10);
// Allocate threads
pthread_t threads[count];
// Create & initialize sum structure
sum_t sum;
pthread_mutex_init(&(sum.lock), NULL);
sum.sum = 0;
// Run sum threads
for (long i = 0; i < count; ++i) {
pthread_create(&(threads[i]), NULL, do_sum, &sum);
}
// Wait until they have finished
for (long i = 0; i < count; ++i) {
pthread_join(threads[i], NULL);
}
// Destroy the mutex lock
pthread_mutex_destroy(&(sum.lock));
// Print result
printf("%ld\n", sum.sum);
return 0;
}
My program's desired functionality:
Using the command line user inputs N and M. N is the number of new threads that will be created and M is the number of how much every thread increments the global variable A.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
static int A = 0;
void *Thread(void* x){
int i;
int n = *((int*)x);
for (i = 0; i<n; i++){
A++;
}
}
int main(int argc, char* argv[]){
int i;
int N = atoi(argv[1]);
int M = atoi(argv[2]);
pthread_t *thread = (pthread_t *) malloc(sizeof(pthread_t)*N);
if(!thread){
printf("No memory\n");
exit(2);
}
for (i = 0; i< N; i++){
if (pthread_create(&thread[i], NULL, Thread, &M)){
printf("Not able to create a thread\n");
exit(1);
}
}
for(i = 0; i< N; i++)
pthread_join(thread[i], NULL);
printf("A = %d\n", A);
return 0;
}
The problem is that every time I run it there's a different output.
Screenshot of my terminal when i run the program multiple times in a row
The problem is that you are creating multiple threads that in parallel are trying to modify your static A global variable at the same time, without any kind of protection.
That means that depending on the scheduling of the threads, the changes on your global variable will not be atomic, producing this effect.
You can solve this with a mutex, declare it with:
pthread_mutex_t mutex;
And initialise / release it with pthread_mutex_init and pthread_mutex_destroy.
Inside of the thread, before doing the change protect the resource to change with pthread_mutex_lock, and release it with pthread_mutex_unlock. So the code will be changed like this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
static int A = 0;
pthread_mutex_t mutex;
void *Thread(void* x){
int i;
int n = *((int*)x);
pthread_mutex_lock(&mutex);
A += n;
pthread_mutex_unlock(&mutex);
}
int main(int argc, char* argv[]){
int i;
int N = atoi(argv[1]);
int M = atoi(argv[2]);
pthread_mutex_init(&mutex, NULL);
pthread_t *thread = (pthread_t *) malloc(sizeof(pthread_t)*N);
if(!thread){
printf("No memory\n");
exit(2);
}
for (i = 0; i< N; i++){
if (pthread_create(&thread[i], NULL, Thread, &M)){
printf("Not able to create a thread\n");
exit(1);
}
}
for(i = 0; i< N; i++)
pthread_join(thread[i], NULL);
printf("A = %d\n", A);
pthread_mutex_destroy(&mutex);
return 0;
}
I have written the code below but when I run it it brings segmentation fault. It compiles correctly though. Where are my mistakes?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
static int N = 5;
static void* run(void *arg) {
int *i = (int *) arg;
char buf[123];
snprintf(buf, sizeof(buf), "thread %d", *i);
return buf;
}
int main(int argc, char *argv[]) {
int i;
pthread_t *pt = NULL;
for (i = 0; i < N; i++) {
pthread_create(pt, NULL, run, &i);
}
return EXIT_SUCCESS;
}
Any hint is welcomed.
Thank you
You have serveral issues:
1) You are passing a NULL to pthread_create() which is probably the reason for segfault.
2) You don't wait for the threads to complete (when main thread exits the whole process dies).
3) You are passing the address same variable i to all threads. This is a data race.
4) You are returning the address of a local variable buf from the thread function.
You can fix it like:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
static int N = 5;
static void* run(void *arg) {
int *i = (int *) arg;
char *buf = malloc(16);
snprintf(buf, 16, "thread %d", *i);
return buf;
}
int main(int argc, char *argv[]) {
int i;
void *ret;
int arr[N];
pthread_t pt[N];
for (i = 0; i < N; i++) {
arr[i] = i;
pthread_create(&pt[i], NULL, run, &arr[i]);
}
for (i = 0; i < N; i++) {
pthread_join(pt[i], &ret);
printf("Thread %d returned: %s\n", i, (char*)ret);
free(ret);
}
return EXIT_SUCCESS;
}
Note that you don't need to use pthread_join() calls. You can also cal pthread_exit() from the main thread so that only the main thread exit and other threads continue.
Problem: Implement a program that gets as arguments a file name followed by words. For each word, create a separate thread that counts its appearances in the given file.Print out the sum of the appearances of all words.
Below I did a code but I receive : Segmentaion Fault (core dumped) when I run it.
PS: I do not know if the code is correct and does the requirement succesfully
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mtx;
int sum = 0;
char filename[10];
char word[10];
void * voidCount(void* p){
char cmd[100], appearences[100];
FILE *f;
sprintf(cmd, "echo %s | grep -o %s | wc -l", filename, word);
f = popen(cmd, "r");
fgets(appearences, sizeof(int), f);
pthread_mutex_lock(&mtx);
sum += *((int*)appearences);
pthread_mutex_unlock(&mtx);
return NULL;
}
int main(int argc, char *argv[]){
pthread_mutex_init(&mtx, NULL);
pthread_t threads[argc-1];
int i = 0;
for ( i = 1; i < argc-1; i++){
strcpy(filename, argv[1]);
strcpy(word, argv[i]);
pthread_create(&threads[i], NULL, voidCount, NULL);
}
for (i = 0; i < argc-1; ++i){
pthread_join(threads[i], NULL);
}
printf("Total appearences: %d", sum);
pthread_mutex_destroy(&mtx);
return 0;
}
The program has to complete few tasks in order to solve the problem:
set the number of threads depending on the number of words to search for
properly allocate and initialize thread arguments
pass each individual word as individual thread argument
protect shared variables during computation
get the results
Here's a minimal functional demo rework of your code with few essential comments. Word search is case sensitive.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mtx;
int sum = 0;
char filename[10]; //declared global for simplicity
//we search all the words in the same file
void * voidCount(void* p){
char *word, cmd[100], appearences[100];
int num;
FILE *f;
word = ((char*)p);
printf ("word : %s\n",word);
sprintf(cmd, "more %s | grep -o %s | wc -l", filename, word);//echo didn't work
printf ("%s\n",cmd); //debug print
pthread_mutex_lock(&mtx);
f = popen(cmd, "r");
if(fgets(appearences, sizeof(appearences), f) == NULL)
printf("Pipe error\n"); //better error handling is welcome...
printf("Appearances of \"%s\": %s\n", word, appearences);
num = atoi(appearances); //convert string to int
sum += num;
pclose(f); //close pipe
pthread_mutex_unlock(&mtx);
return NULL;
}
int main(int argc, char *argv[])
{
pthread_mutex_init(&mtx, NULL);
pthread_t threads[argc-1];
char **data = calloc(argc,sizeof(char*)); // initialize thread data
int i = 0;
strcpy(filename, argv[1]);
for ( i = 2; i < argc; i++){
data[i-2] = calloc(33, sizeof(char));//let's allow for somewhat longer words
strcpy(data[i-2], argv[i]);
strcat(data[i-2], "\0");
pthread_create(&threads[i-2], NULL, voidCount, data[i-2]);//each word a thread arg
}
for (i = 0; i < argc-1; ++i){;
pthread_join(threads[i], NULL);
}
printf("Total appearences: %d\n", sum);
pthread_mutex_destroy(&mtx);
for (i = 0; i < argc; i++)//free thread data
free (data[i]);
free (data);
return 0;
}
Hope this can help.
I'm experimenting with pthreads and for the following code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* print_thread_num(void *index);
int main(int argc, char** argv) {
int i;
pthread_t threads[3];
for (i = 0; i < 3; i++) {
void *index = &i;
printf("Creating thread %d\n", i);
pthread_create(&threads[i], NULL, print_thread_num, index);
}
pthread_exit(NULL);
}
void* print_thread_num(void *index) {
int i = *(int*)index;
printf("I am the thread at index %d\n", i);
pthread_exit(NULL);
}
I'm getting the output below:
Creating thread 0
Creating thread 1
I am the thread at index 1
Creating thread 2
I am the thread at index 2
I am the thread at index 3
Why is each "I am the thread at index" printing an index higher than what it should print?
You're passing the address of your loop variable i, this is being incremented in the main thread while your child threads access it.