I just started learning about thread today, and wanted to test the race condition of threads by running two codes with/without mutex.
#define HAVE_STRUCT_TIMESPEC
#include <pthread.h>
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#define NTHREADS 3
#define ITERATIONS (long long) 1000000000
//pthread_mutex_t mutex;
static long long counter = 0;
static void * thread_f(void * arg) {
unsigned long long i;
(void)arg;
for (i = 0; i != ITERATIONS; i++) {
// pthread_mutex_lock(&mutex);
counter = counter + 1;
// pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(void) {
pthread_t threads[NTHREADS];
int i;
for (i = 0; i != NTHREADS; i++)
pthread_create(&threads[i], NULL, thread_f, NULL);
for (i = 0; i != NTHREADS; i++)
pthread_join(threads[i], NULL);
printf("expected = %lld, actual = %lld\n", NTHREADS*ITERATIONS, counter);
printf("experienced %lld race conditions\n", NTHREADS*ITERATIONS - counter);
system("pause");
return 0;
}
So, without mutex, the program prints out these following lines on cmd:
expected = 3000000000, actual = 1174158414
experienced 1825841586 race conditions
However, if I put mutex in the code, and run the program, cmd pops up then shuts down itself without showing any result.
I want to know if I coded anything wrong or is misusing mutex lines as I really don't know much about threads.
p.s this is coded in windows 10, using visual studio
Thanks to EOF from the comment, I found out that I did not initialize mutex in the code.
I simply added:
if (pthread_mutex_init(&mutex, NULL)) {
printf("Something went wrong\n");
return 1;
}
this in the main, and everything works fine now.
Related
First of all I am still new to posix programming and still understanding basic concepts. It is still not very clear for me how do pthread_mutex_lock
pthread_mutex_unlock do work.
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <pthread.h>
#inlcude <stdio.h>
pthread_mutex_t_mtx;
void* routine(void* i){
int j;
for(j = 0; j < 1000000; ++j){
pthread_mutex_lock(&mtx);
printf("Inside thread %d\n", i);
pthread_mutex_unlock(&mtx);
}
return NULL;
}
int main()
{
pthread_t th[3];
int i;
pthread_mutex_init(&mtx, NULL);
for(i = 1; i <= 2; ++i)
{
if(pthread_create(th + i, NULL, routine, i){
perror(NULL); return 1;
}
}
for(i = 1; i <=2; ++i)
pthread_join(th[i], NULL);
return 0;
}
What should be the correct output of the above program ? I think that because of the lock and unlock of the mutex there would be 2000000 iterations, but it is not very clear for me the order that they are done in. Does the first thread execute the first 1000000 steps of the for? Does it even execute the first one of the 20000000 ? Or does this happen by a more chaotic order?
Assuming that the mutex is a global one, you will get 2000000 messages, with 1000000 from each thread. The order of those is random, however they will not interfere each other as each print is protected by the mutex
EDIT: I just noticed, that you are joining before creating the next thread. Therfore first there will be all messages of the first, then of the second thread. In this case the mutex has no effect at all. The reason for the ordering is simply that you will not have more then one worker-thread running at the same time.
I'm a novice in C and trying to learn Multi Threading.
I played aroud with a C program counting to 100000 with 2 threads and outputing to text.
However, my program seem to have seg. fault.
I cannot figure it out.
Please Help :)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define COUNT_TO 100000
#define MAX_CORES 2
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
long long i = 0;
void *start_counting(FILE *out)
{
//lock
pthread_mutex_lock(&mutex);
while (i < COUNT_TO)
{
++i;
printf("i = %lld\n", i);
fprintf(out,"i = %lld\n", i);
}
//lock
pthread_mutex_unlock(&mutex);
}
int main(void)
{
int i = 0;
FILE *out;
out = fopen("output.txt","w");
// create a thread group the size of MAX_CORES
pthread_t *thread_group = malloc(sizeof(pthread_t) * MAX_CORES);
// start all threads to begin work
for (i = 0; i < MAX_CORES; ++i)
{
pthread_create(&thread_group[i], NULL, start_counting(out), NULL);
}
// wait for all threads to finish
for (i = 0; i < MAX_CORES; ++i)
{
pthread_join(thread_group[i], NULL);
}
fclose(out);
return EXIT_SUCCESS;
}
You have a error in this call:
pthread_create(&thread_group[i], NULL, start_counting(out), NULL);
It should be:
pthread_create(&thread_group[i], NULL, start_counting, out);
Please refer to the manual at https://man7.org/linux/man-pages/man3/pthread_create.3.html
I am new to POSIX and I cant find a solution to this particular problem.
Are there any known issues with creating pthreads inside of loop with big number of iterations(>100000)?
It seems like every time I execute, it hangs on a random pthread_join.
I've tested for memory leaks and thread stack usage with valgrind.
If I interrupt gdb when the program hangs it will trace the problem to pthread_join.
This is example code recreates my problem.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* task(void* args);
int main(int argc, char **argv)
{
int num_threads = 4;
int m = 100000;
int i;
for(i = 0; i < m; i++)
{
fprintf(stdout, "i:%d\n",i);
//parallel region starts
pthread_t threads[num_threads];
int t,rc;
for(t = 0; t < num_threads; t++)
{
rc = pthread_create(&threads[t],NULL,task,NULL);
if(rc){
fprintf(stderr,"ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for(t = 0; t < num_threads; t++)
{
rc = pthread_join(threads[t],NULL);
if(rc){
fprintf(stderr,"ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
}
//parallel region ends
}
pthread_exit(NULL);
}
//thread task
void* task(void* args)
{
pthread_exit(NULL);
}
Verified your code on an Ubuntu machine i7-4600U CPU # 2.10GHz
I don't see any issue with your code, just to verify i compiled and run your code on my local machine it seems to work fine.
i got the output as expected:
i:999,j:999
so I am assuming the issue you you are experiancing has something to do with your environment. what CPU OS and GCC are you using?
I'm trying to synchronize multiple (7) threads. I thought I understood how they work until I was trying it on my code and my threads were still printing out of order. Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
void *text(void *arg);
long code[] = {4,6,3,1,5,0,2}; //Order in which to start threads
int num = 0;
pthread_mutex_t lock; //Mutex variable
int main()
{
int i;
pthread_t tid[7];
//Check if mutex worked
if (pthread_mutex_init(&lock, NULL) != 0){
printf("Mutex init failed\n");
return 1;
}
//Initialize random number generator
time_t seconds;
time(&seconds);
srand((unsigned int) seconds);
//Create our threads
for (i=0; i<7; i++)
pthread_create(&tid[i], NULL, text, (void*)code[i]);
//Wait for threads to finish
for (i=0; i<7; i++){
if(pthread_join(tid[i], NULL)){
printf("A thread failed to join\n");
}
}
//Destroy mutex
pthread_mutex_destroy(&lock);
//Exit main
return 0;
}
void *text (void *arg)
{
//pthread_mutex_lock(&lock); //lock
long n = (long) arg;
int rand_sec = rand() % (3 - 1 + 1) + 1; //Random num seconds to sleep
while (num != n) {} //Busy wait used to wait for our turn
num++; //Let next thread go
sleep(rand_sec); //Sleep for random amount of time
pthread_mutex_lock(&lock); //lock
printf("This is thread %d.\n", n);
pthread_mutex_unlock(&lock); //unlock
//Exit thread
pthread_exit(0);
}
So here I am trying to make threads 0-6 print IN ORDER but right now they are still scrambled. The commented out mutex lock is where I originally had it, but then moved it down to the line above the print statement but I'm having similar results. I am not sure where the error in my mutex's are, could someone give a hint or point me in the right direction? I really appreciate it. Thanks in advance!
You cannot make threads to run in order with only a mutex because they go in execution in an unpredictable order.
In my approach I use a condition variable and a shared integer variable to create a queueing system. Each thread takes a number and when the current_n number is equal to the one of the actual thread, it enters the critical section and prints its number.
#include <pthread.h>
#include <stdio.h>
#define N_THREAD 7
int current_n = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t number = PTHREAD_COND_INITIALIZER;
void *text (void *arg) {
int i = (int)arg;
pthread_mutex_lock(&mutex);
while ( i > current_n ) {
pthread_cond_wait(&number, &mutex);
}
//i = current_n at this point
/*I use stderr because is not buffered and the output will be printed immediately.
Alternatively you can use printf and then fflush(stdout).
*/
fprintf(stderr, "I'm thread n=%d\n", i);
current_n ++;
pthread_cond_broadcast(&number);
pthread_mutex_unlock(&mutex);
return (void*)0;
}
int main() {
pthread_t tid[N_THREAD];
int i = 0;
for(i = 0; i < N_THREAD; i++) {
pthread_create(&tid[i], NULL, text, (void *)i);
}
for(i = 0; i < N_THREAD; i++) {
if(pthread_join(tid[i], NULL)) {
fprintf(stderr, "A thread failed to join\n");
}
}
return 0;
}
The output is:
I'm thread n=0
I'm thread n=1
I'm thread n=2
I'm thread n=3
I'm thread n=4
I'm thread n=5
I'm thread n=6
Compile with
gcc -Wall -Wextra -O2 test.c -o test -lpthread
Don't worry about the warnings.
Using trylock:
FILE *fp;
pthread_mutex_t demoMutex;
void * printHello (void* threadId)
{
pthread_mutex_trylock (&demoMutex);
pthread_t writeToFile = pthread_self ();
unsigned short iterate;
for (iterate = 0; iterate < 10000; iterate++)
{
fprintf (fp, " %d ", iterate, 4);
fprintf (fp, " %lu ", writeToFile, sizeof (pthread_t));
fprintf (fp, "\n", writeToFile, 1);
}
pthread_mutex_unlock (&demoMutex);
pthread_exit (NULL);
}
and then main ():
int main ()
{
pthread_t arrayOfThreadId [5];
int returnValue;
unsigned int iterate;
fp = fopen ("xyz", "w");
pthread_mutex_init (&demoMutex, NULL);
for (iterate = 0; iterate < 5; iterate++)
{
if (returnValue = pthread_create (&arrayOfThreadId [iterate],
NULL,
printHello,
(void*) &arrayOfThreadId [iterate]) != 0)
{
printf ("\nerror: pthread_create failed with error number %d", returnValue);
}
}
for (iterate = 0; iterate < 5; iterate++)
pthread_join (arrayOfThreadId [iterate], NULL);
return 0;
}
Here the output first prints some of the first thread and then the rest, and then again the first. The lock isn't working. If I replace the same with pthread_mutex_lock every thing gets shown very sequentially!
What's the ridiculous mistake here?
It does not make sense to call pthread_mutex_trylock() without testing the result.
If it fails to acquire the mutex, you should not enter the critical section, and you should not unlock it later. For example, you could rewrite it like so (note that you are also very confused about how fprintf() should be called):
void *printHello(void *threadId)
{
if (pthread_mutex_trylock(&demoMutex) == 0)
{
unsigned short iterate;
for (iterate = 0; iterate < 10000; iterate++)
{
fprintf (fp, " %d\n", iterate);
}
pthread_mutex_unlock (&demoMutex);
}
pthread_exit (NULL);
}
However, it probably makes more sense to use pthread_mutex_lock() instead of pthread_mutex_trylock(), so that your thread will wait for the mutex to be available if it is contended. pthread_mutex_lock() is in almost all cases what you want; the _trylock variant is only for optimising some unusual cases - if you ever encounter a situation where _trylock is needed, you'll know.
...
while (pthread_mutex_trylock(&demoMutex) == 0)
...
Your code makes no sense. Where is it force locked? It's like a not working spinlock that use more CPU?!
trylock returns 0 when it locks, so:
if(!pthread_mutex_trylock(&demoMutex))
{
// mutex locked
}
The pthread_mutex_trylock() function shall return zero if a lock on
the mutex object referenced by mutex is acquired. Otherwise, an error
number is returned to indicate the error.
caf had a great answer on how to use it. I just had to grab that explanation for myself, however I did learn that pthread_mutex_lock() has far more overhead in class and just tested it out using the <time.h> lib and the performance for my loop was significantly increased. Just adding in that two cents since he mentioned that maybe you should use pthread_mutex_lock() instead!
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUM_THREADS 4
#define LOOPS 100000
int counter;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// using pthread_mutex_lock
void* worker() {
for (int i = 0; i < LOOPS; i++) {
pthread_mutex_lock(&mutex);
counter++;
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
// using try_lock - obviously only use one at a time
void* worker() {
for (int i = 0; i < LOOPS; i++) {
while (pthread_mutex_trylock(&mutex) != 0) {
// wait - treated as spin lock in this example
}
counter++;
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
clock_t begin = clock();
pthread_t t[NUM_THREADS];
int rc;
counter = 0;
for (int i = 0; i < NUM_THREADS; i++) {
rc = pthread_create(&t[i], NULL, worker, NULL);
if (rc) {
printf("Thread #%d failed\n", i);
}
}
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(t[i], NULL);
}
printf("%d\n", counter);
clock_t end = clock();
double time = (double)(end - begin) / CLOCKS_PER_SEC;
printf("Time Spent: %f", time);
return 0;
}
Obviously you would comment out one worker to test it, but if you try it out, I get Time Spent: 1.36200 as an average for pthread_mutex_lock() and Time Spent: 0.36714 for pthread_mutex_trylock().
Goes faster again if you use Atomics.
The code is meant to block to ensure mutual exclusion where you call pthread_mutex_trylock(). Otherwise it is undefined behavior. Therfore you must call pthread_mutex_lock().
a modified version of force locked with while loop should be more stable.
void *printHello(void *threadId)
{
while (pthread_mutex_trylock(&demoMutex) == 0)
{
unsigned short iterate;
for (iterate = 0; iterate < 10000; iterate++)
{
fprintf (fp, " %d\n", iterate);
}
pthread_mutex_unlock (&demoMutex);
break;
}
pthread_exit (NULL);
}`
The use of pthread_mutex_trylock is used to ensure that tou will not cause a race to a specific command.
In order to do so, you must use pthread_mutex_trylock as a condition! an not assume that it would work by it self.
example-
while(pthread_mutex_trylock(&my_mutex)==0){
printf("The mutex is in my control!!\n");
}
that way you can be sure that even if the mutex is now locked, you are doing abusy-waiting for it in that particular thread.