#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* thread_even(void* arg);
void* thread_odd(void* arg);
int main(int argc, char** argv) {
pthread_t tid[2];
pthread_create(&tid[0], 0, &thread_even, 0);
pthread_create(&tid[1], 0, &thread_odd, 0);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}
void* thread_even(void* arg) {
int* thread_id = (int*)arg;
pthread_mutex_lock(&mutex);
for(int i = 1; i <= *thread_id; i++)
{
if(i%2 != 0)
{
printf("Thread 1: %d", i);
}
}
pthread_mutex_unlock(&mutex);
return NULL;
}
void* thread_odd(void* arg) {
int* thread_id = (int*)arg;
pthread_mutex_lock(&mutex);
for(int i = 1; i <= *thread_id; i++)
{
if(i%2 == 0)
{
printf("Thread 2: %d", i);
}
}
pthread_mutex_unlock(&mutex);
return NULL;
}
The above is the code I am working on but I get a segment fault error... What I want to achieve is, for example,
when I compile it and run with an argument 8 (./number 8)
it should print out
thread 1: 1
thread 2: 2
thread 1: 3
... etc till the number, 8.
in which thread 1s should represent the even numbers and the thread 2s stand for the odd numbers.
Please help... I want to develop my knowledge about C but have no one to ask..
Thanks.
Looks like you are passing 0 AKA NULL to the last parameter of pthread_create, and then doing the following:
int* thread_id = (int*)arg;
pthread_mutex_lock(&mutex);
for(int i = 1; i <= *thread_id; i++)
So, thread_id will certainly be NULL, referencing it will be a SEGFAULT.
If you want to pass an upper bound for each thread to run to, do you can do something like this:
int main(int argc, char** argv) {
pthread_t tid[2];
int *ids = malloc(2 * sizeof(int));
ids[0] = 10; /* upper bound for thread 1 */
ids[1] = 10; /* upper bound for thread 2 */
pthread_create(&tid[0], 0, &thread_even, &ids[0]);
pthread_create(&tid[1], 0, &thread_odd, &ids[1]);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
free(ids);
return 0;
}
There are ways to do this without resorting to heap allocation, but this is the most straight forward.
Related
I'm trying to use semaphores to avoid that a global variable is changed by threads and this variable is supposed to increment within the for loop. My main objective is to protect the variable cnt from the threads so it can increment within the for loop. However, I don't know how to do it because this is the first time I work with semaphores.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
sem_t semaphore;
int cnt = 0; //global shared variable
void *threadProd(void *param); //threads call this function.
int main(int argc, char *argv[])
{
int niters;
pthread_t tid1, tid2; //thread ids
sem_init(&semaphore,0,1);
if (argc != 2){
printf("Usage: %s <niters>\n", argv[0]);
exit(0);
}
niters = atoi(argv[1]);
pthread_create(&tid1, NULL, threadProd, &niters);
pthread_create(&tid2, NULL, threadProd, &niters);
pthread_join(tid1, NULL); //wait for thread to finish
pthread_join(tid2, NULL);
//check answer:
if(cnt != (2 * niters))
printf("Incorrect answer, cnt = %d\n", cnt);
else
printf("Correct answer, cnt = %d\n", cnt);
sem_destroy(&semaphore);
exit(0);
}
//Thread routine
void *threadProd(void *vargp)
{
sem_wait(&semaphore);
int upper = *((int *) vargp);
for (int i = 0; i < upper; i++)
cnt ++;
sem_post(&semaphore);
return NULL;
}
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;
}
I am writing a multi-threaded application that reads a file and seeks for a word in chunks of it a thread has in memory.
A thread needs to asynchronously close other threads looking for that word if it is first to find it.
The problem is when a word is found and other threads are being closed the program does not terminate (in 6 out of 10 executions). I have checked in gdb that one thread does not exit. It happens even when I do not call waitforthreads(n_threads).
// [...]
FILE* f;
pthread_mutex_t mutex;
pthread_t* threads;
int n_threads;
int allread;
// [...]
int main(int argc, char* argv[]) {
// [...]
threads = (pthread_t*) calloc(n_threads, sizeof(pthread_t));
pthread_mutex_init(&mutex, NULL);
runthreads(f, word, n_threads, n_records);
waitforthreads(n_threads);
pthread_mutex_destroy(&mutex);
// [...]
}
void runthreads(FILE* f, char* w, int n_threads, int n_records) {
struct targs_t args = {w, n_records};
for (int i=0; i<n_threads; i++)
pthread_create(&threads[i], NULL, findword, (void*) &args);
}
void waitforthreads(int N) {
for (int i=0; i<N; i++)
if(pthread_join(threads[i], NULL))
exit_(6);
}
void* findword(void* arg) {
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
struct targs_t* args = (struct targs_t*) arg;
int max_length = args->n_records * sizeof(record_t);
record_t* records = malloc(max_length);
int found = 0;
while (!allread && !found) {
pthread_mutex_lock(&mutex);
// allread is being set in the function below
// if the whole file has been read
readRecords((char*) records, args->n_records, f);
pthread_mutex_unlock(&mutex);
for (int i=0; i<args->n_records; i++)
if (strlen(records[i].text) == 0) break;
else if (strstr(records[i].text, args->word) != NULL) {
notifyfound(pthread_self(), records[i].id);
found = 1;
break;
}
}
free(records);
return NULL;
}
void notifyfound(pthread_t tid, int id) {
printf("Found: %d (%ld)\n", id, (long) tid);
for (int i=0; i<n_threads; i++)
if (threads[i] && !pthread_equal(threads[i], tid)) {
printf(" closing %ld\n", (long) threads[i]);
pthread_cancel(threads[i]);
}
printf(" finished closing\n");
}
This has to do with cancellation points, although the specifics are hard to come by since you haven't shared a minimal example. My diagnosis is either
6/10 times you have at least one thread waiting for a mutex, and other one in readRecords, which will cancel and not free the mutex. Setup cancellation handlers with pthread_cleanup_push and pthread_cleanup_pop which will free your mutex, and read the manual for pthread_cancel. See related pthread_cleanup_push causes Syntax error for some references.
Some of your threads are not detecting the cancellation - try using pthread_testcancel to setup a guaranteed cancellation point.
Here is some code that fixes these sorts of problems, by adding a cancellation check and mutex cleanup.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
FILE* f;
pthread_mutex_t mutex;
pthread_t* threads;
int n_threads = 3;
int allread;
long int count = 0;
int *thread_ids;
int global_quit = 0;
#define MAX 99999
void waitforthreads(int N) {
printf("waiting for %d threads\n", N);
for (int i=0; i<N; i++)
{
printf("thread %d | %d\n", i, threads[i]);
if(pthread_join(threads[i], NULL))
{
printf("problem\n");
exit(6);
}
}
printf("done.\n");
}
void notifyfound(pthread_t tid, int count) {
printf("%d | %d got big number\n", count, pthread_self());
for (int i=0; i<n_threads; i++)
if (threads[i] && !pthread_equal(threads[i], tid)) {
printf(" closing '%ld'\n", (long) threads[i]);
pthread_cancel(threads[i]);
}
global_quit = 1;
printf(" finished closing\n");
}
void waiting_thread_cleanup(void *arg)
{
pthread_mutex_unlock((pthread_mutex_t *)arg);
}
void* do_thing(void* arg) {
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
int* id = (int *)arg;
int quit = 0;
while (!allread) {
pthread_mutex_lock(&mutex);
pthread_cleanup_push(waiting_thread_cleanup, (void *)&mutex); /* must be paired with pop. */
if(count++==MAX)
{
notifyfound(pthread_self(), *id);
quit=1;
}
else if(count % 10000 == 0)
printf("[%d] - %d\n", *id, count);
pthread_testcancel(); /* required to allow for the cancel to ever be 'detected' other functions are sufficient as well. */
pthread_mutex_unlock(&mutex);
pthread_cleanup_pop(1); /* if this isn't here, this will occassionally hand because the mutex isn't freed. */
if(quit==1)
{
printf("%d | %d quitting\n", *id, pthread_self());
break;
}
}
return NULL;
}
void runthreads(FILE* f, int n_threads) {
for (int i=0; i<n_threads; i++)
pthread_create(&threads[i], NULL, do_thing, &(thread_ids[i]));
}
int main(int argc, char* argv[]) {
threads = (pthread_t*) calloc(n_threads, sizeof(pthread_t));
thread_ids = (int*) calloc(n_threads, sizeof(int));
for(int i=0;i<n_threads;i++)
thread_ids[i] = i;
pthread_mutex_init(&mutex, NULL);
runthreads(f, n_threads);
waitforthreads(n_threads);
pthread_mutex_destroy(&mutex);
}
Following scenario:
We are supposed to make x Threads maximum. Our main-function is supposed to make a single new thread with a pointer to the function 'makeThreads'. This function is supposed to make up to 2 threads, depending on how many threads are already there. Race conditions are to avoid.
I'm stuck. I'm not exactly sure how to solve the problem I'm running into, partly because I don't can't identify the problem itself.
Suggestions are greatly appreciated!
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#define MAX_THR 20
pthread_mutex_t mutex;
int threadCount = 0;
int randomNbr(){
int number = (rand() % 10) + 1;
return number;
}
void *makeThreads(void* number){
int rndnmb = *((int *) number);
pthread_mutex_lock(&mutex);
sleep(rndnmb);
pthread_t threadDummy;
int thread1, i, threadID, rndnbr;
threadID = threadCount;
printf("Hello from Thread %d!\n", threadID);
for(i = 0; i < 2; i++){
if(threadCount < MAX_THR){
rndnbr = randomNbr();
int *rnd = &rndnbr;
threadCount++;
thread1 = pthread_create(&threadDummy, NULL, *makeThreads, (void *) rnd);
pthread_join(threadDummy, NULL);
}
}
pthread_mutex_unlock(&mutex);
printf("Goodbye from Thread %d!\n", threadID);
}
int main(){
int t1, rndnbr;
pthread_t threadOne;
pthread_mutex_init(&mutex, NULL);
srand(time(NULL));
rndnbr = randomNbr();
int *rnd = &rndnbr;
threadCount++;
t1 = pthread_create(&threadOne, NULL, *makeThreads, (void *) rnd);
pthread_join(threadOne, NULL);
}
I am trying to use pthread mutex variables and barrier to synchronize the output of my program, but it is not working the way I want it to. Each thread is seeing its final value every 20 values (coming from the for loop) which is alright but I'm trying to make them all get to the same final value (if using 5 threads, all of them should see 100 as final value, with 4 threads, 80, etc)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int SharedVariable =0;
void *SimpleThread(void *args)
{
int num,val,rc;
int which =(int)args;
rc = pthread_mutex_lock(&mutex1);
for(num=0; num<20; num++){
#ifdef PTHREAD_SYNC
if(random() > RAND_MAX / 2)
usleep(10);
#endif
//pthread_mutex_lock(&mutex1);
val = SharedVariable;
printf("*** thread %d sees value %d\n", which, val);
//pthread_mutex_lock(&mutex1);
SharedVariable = val+1;
pthread_mutex_unlock(&mutex1);
}
val=SharedVariable;
printf("Thread %d sees final value %d\n", which, val);
//pthread_mutex_destroy(&mutex1);
//pthread_exit((void*) 0);
//pthread_mutex_unlock(&mutex1);
}
int main (int argc, char *argv[])
{
if(atoi(argv[1]) > 0){
int num_threads = atoi(argv[1]);
//pthread_mutex_init(&mutex1, NULL);
pthread_t threads[num_threads];
int rc;
long t;
rc = pthread_mutex_lock(&mutex1);
for(t=0; t< num_threads; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, SimpleThread, (void* )t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
//pthread_join(thread1);
}
rc= pthread_mutex_unlock(&mutex1);
}
else{
printf("ERROR: The parameter should be a valid positive number.");
exit(-1);
}
pthread_mutex_destroy(&mutex1);
pthread_exit(NULL);
}
Any suggestions or help is greatly appreciated!
Thanks in advanced!
You need to use a barrier (pthread_barrier_wait()) before checking for the final value - this ensures that no thread will proceed until all threads have reached the barrier.
In addition, you should be calling pthread_join() to wait for the threads to finish, and you only need to hold the mutex around the increment:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_barrier_t barrier1;
int SharedVariable = 0;
void *SimpleThread(void *args)
{
int num,val;
int which = (int)args;
for(num = 0; num < 20; num++) {
#ifdef PTHREAD_SYNC
if(random() > RAND_MAX / 2)
usleep(10);
#endif
pthread_mutex_lock(&mutex1);
val = SharedVariable;
printf("*** thread %d sees value %d\n", which, val);
SharedVariable = val + 1;
pthread_mutex_unlock(&mutex1);
}
pthread_barrier_wait(&barrier1);
val = SharedVariable;
printf("Thread %d sees final value %d\n", which, val);
return 0;
}
int main (int argc, char *argv[])
{
int num_threads = argc > 1 ? atoi(argv[1]) : 0;
if (num_threads > 0) {
pthread_t threads[num_threads];
int rc;
long t;
rc = pthread_barrier_init(&barrier1, NULL, num_threads);
if (rc) {
fprintf(stderr, "pthread_barrier_init: %s\n", strerror(rc));
exit(1);
}
for (t = 0; t < num_threads; t++) {
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, SimpleThread, (void* )t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for (t = 0; t < num_threads; t++) {
pthread_join(threads[t], NULL);
}
}
else {
printf("ERROR: The parameter should be a valid positive number.\n");
exit(-1);
}
return 0;
}
Try to move the pthread_mutext_unlock(&mutext1) out of the for loop in your SimpleThread. You lock once and unlock mutiple(20) times in your original code.
Alternatively, you could move pthread_mutex_lock(&mutext1) into the for loop, just before you read and modify your SharedVariable. In this case, each thread's add-by-one operation may not consecutive but each thread will get the correct final value.
And before you read the final value of the SharedVariable, use a barrier to wait all the threads finish their job.