How to synchronize threads? - c

I used threads in this code. but when I execute this code in shell, some threads didn't print this line.
printf("\ti'm %dth thread:)", j);
printf("\t%c %d %d %d \n", arr[j].op, arr[j].byte, seq, no_file);
In addition, even some threads print this line twice. what happened to this process? And how to reorganize this code in order to threads print the line exactly once?
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
typedef struct {char op; int byte; int seq; int no_file; } ARRAY;
ARRAY *arr;
void *thread_operation(void *arg){
int j =*((int*)arg);
seq = arr[j].seq;
int no_file = arr[j].no_file;
printf("\ti'm %dth thread:)", j);
printf("\t%c %d %d %d \n", arr[j].op, arr[j].byte, seq, no_file);
}
int main()
{
int err, j, i = 10;
long int tid;
arr = (ARRAY*)malloc(sizeof(ARRAY) * i);
srand(time(NULL));
for (i = 0; i <= 10; i++){
arr[i].op = 'r';
arr[i].byte = (rand() % 10);
arr[i].seq = i;
arr[i].no_file = i + 10;
}
for(j = 0; j < 10; j++){
printf("creating %dth thread.....", j);
err = pthread_create(&tid, NULL, thread_operation, &j);
if(err != 0)
printf("%s\n", strerror(err));
printf("%dth done\n", j);
}
return 0;
}
This is result from my pc
creating 0th thread.....0th done
creating 1th thread..... i'm 0th thread:) r 9 0 10
1th done
creating 2th thread..... i'm 2th thread:) r 3 2 12
i'm 2th thread:) r 3 2 12
2th done
creating 3th thread..... i'm 3th thread:) r 6 3 13
3th done
creating 4th thread..... i'm 4th thread:) r 9 4 14
4th done
creating 5th thread..... i'm 5th thread:) r 3 5 15
5th done
creating 6th thread..... i'm 6th thread:) r 2 6 16
6th done
creating 7th thread..... i'm 7th thread:) r 2 7 17
7th done
creating 8th thread.....8th done
creating 9th thread..... i'm 8th thread:) r 6 8 18
9th done
i'm 9th thread:) r 8 9 19
i'm 9th thread:) r 8 9 19

You need to use mutexes ton avoid race conditions, and you also need to use pthread_join to synchronize all your threads before the process dies.
Mutexes allow you to stop some threads while one of them is executing an action using a shared ressource (see man pthread_mutex_lock, pthread_mutex_init)
pthread_join is essential in your code, because it forces your main thread to wait for the other threads you created, if you don't use it, you're not sure all threads will be finished when the main thread returns from the main.

The reason why some are printing out twice (such as thread number 9) is because you are passing a pointer to your loop variable as the input to the thread_operation.
for(j = 0; j < 10; j++){
err = pthread_create(&tid, NULL, thread_operation, &j);<---here
that &j is eventually dereferenced by thread_operation:
void *thread_operation(void *arg){
int j =*((int*)arg);<---here
but at this point the loop could have advanced and the value of j (in the thread operation) will be whatever j happens to be in the loop right now. The way to fix this is to not pass a pointer but the value of j to the thread constructor. Change your pthread_create to pass the value:
pthread_create(&tid, NULL, thread_operation, (void*) j);
and in your thread cast the value out of the thread argument:
int j =(int)arg;
Now technically this relies on the fact that int and void* are the same size when in general they are not. But this will work as long as you aren't using giant int values.
for all the other problems #Intrepidd is right about using pthread_join to make sure that the process doesn't exit before all your threads complete.

Using printf with incomplete lines between threads will usually not work. You may get the output completely mangled. Also the order in which lines appear on your screen will in general not be the execution order but the order the threads access the shared resource stdout.

Related

Segmentation Fault (Core Dumped), but things seem to work out in my terminal

I must write a program named "matrizdinamica.c" that creates an m x n matrix, where m and p are argv[1] and argv[2]. The matrix elements are of type long int and are computed according to the following rules:
Row no. 1: each element is 1
Column no.1: each element is 1
The remaining elements: x[i][j]=x[i-1][j]+x[i][j-1]; If x[i][j] > 10^6, then x[i][j]=1.
Once the matrix is created, I must write it on the stdout in matrix format. It mus be one line per row that must end always with "\n". Use the format "%li\t" for each element, except for the elements in the last column, in which case "%li\n" must be used.
If the matrix couldn't be created due to memory issues, the program must show nothing and return the code 71. If there are no issues, return 0. Upon termination, all the memory must be freed before the program terminates.
If we suppose our program is called "matrizdinamica", the command "./matrizdinamica 4 5" would produce:
1 1 1 1 1
1 2 3 4 5
1 3 6 10 15
1 4 10 20 35
The code must work for large values of m and p.
So far, when I execute the following comands in order I get the desired result.
y16m038#triqui1:~/clases_pps/entregas_2022-23/4al6$ !gcc
gcc -ansi -pedantic -Wall -Wextra -Werror matrizdinamica matrizdinamica.c
y16m038#triqui1:~/clases_pps/entregas_2022-23/4al6$ ./matrizdinamica 4 5
1 1 1 1 1
1 2 3 4 5
1 3 6 10 15
1 4 10 20 35
Here's my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int filas = strtol(argv[1], NULL, 10);
int columnas = strtol(argv[2], NULL, 10);
long int **x;
int i; /* Recorre filas*/
int j; /* Recorre columnas */
/*Reserva de Memoria*/
x = (long int **) malloc (filas*sizeof(long int*));
if(x==NULL){
printf("Error: outta memory");
exit(71);
}
for (i=0;i<filas;i++){
x[i] = (long int*)malloc(columnas*sizeof(long int));
if (x[i]==NULL) {
exit(71);
}
}
/* Damos Valores a la Matriz*/
for (i=0; i<filas; i++){
for (j=0; j<columnas; j++){
if(i==0) x[i][j]=1;
else if (j==0) x[i][j]=1;
else {
x[i][j]=x[i-1][j]+x[i][j-1];
if (x[i][j]>1000000) x[i][j]=1;
}
}
}
/* Dibujamos la Matriz en pantalla */
for (i=0; i<filas; i++){
/*printf("\n");*/
for (j=0; j<columnas; j++){
if (j==columnas-1){
printf("%li\n", x[i][j]);
}
else {
printf("%li\t", x[i][j]);
}
}
}
/* if (i < filas -1){
printf("\n");}
}*/
/*printf("\n");*/
for(i = 0; i < filas; i++){
free(x[i]);
}
/* free(x);*/
return 0;
}
Could you please help me figure out why the teacher's delivery system says there is a segmentation fault core dump error and also that the exit status is not correct.
Thank you in advance. I hope I made myself clear.
I've tried handling the possible errors when allocating memory and taken care of freeing those memory addresses when I'm done.
I'm expecting to get the assignment approved because it's doing what it's supposed to do, but I don't see where I could be wrong.
There are some minor issues, and one serious problem: if you pass 0 as one or both parameters, the 'malloc' calls will be made for 0 as parameter value. The result of malloc(0) is implementation specific and may be not NULL, so checking for NULL will not detect this.
See: What's the point of malloc(0)?

C, pthreads initialized in loop does not execute assigned function properly despite mutex

I am having trouble debugging my C program where the goal is to create 5 threads and have each of them working on size-2 chunks of an array of length 10. The goal is to get the sum of that array. My actual program is a little less trivial than this as it takes dynamic array sizes and thread counts but I tried simplifying it to this simple problem and it still does not work.
ie.,
array = {1 2 3 4 5 6 7 8 9 10}
then thread1 works on array[0] and array [1]
and thread2 works on array[2] and array[3]
etc...
thread5 works on array[8] and array[9]
However when i run my code, I get weird results, even when using a mutex lock.
For example, this is one of my results when running this program.
Thread #1 adding 3 to 0 New sum: 3
Thread #1 adding 4 to 3 New sum: 7
Thread #2 adding 5 to 7 New sum: 12
Thread #2 adding 6 to 12 New sum: 18
Thread #3 adding 7 to 18 New sum: 25
Thread #3 adding 8 to 25 New sum: 33
Thread #4 adding 9 to 33 New sum: 42
Thread #4 adding 9 to 42 New sum: 51
Thread #4 adding 10 to 51 New sum: 61
Thread #4 adding 10 to 61 New sum: 71
Sum: 71
First of all, why are there no tabs before the "New sum" for the first 3 lines? (see my printf log in calculate_sum function). And more importantly, why is thread0 never executing it's job and why is thread 4 executing twice?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
typedef struct {
int start, end, thread_number;
int *data;
} Func_args;
static pthread_mutex_t mutex;
static int sum = 0;
void *calculate_sum(void *args) {
int *arr = ((Func_args *)args)->data;
int i = ((Func_args *)args)->start;
int end = ((Func_args *)args)->end;
int t_id = ((Func_args *)args)->thread_number;
while (i < end) {
pthread_mutex_lock(&mutex);
printf("Thread #%d adding %d to %d\t", t_id, arr[i], sum);
sum += arr[i++];
printf("New sum: %d\n", sum);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
#define NUM_THREAD 5
#define ARRAY_LEN 10
int main(int argc, char **argv) {
int array[ARRAY_LEN] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
pthread_t tid[NUM_THREAD];
int i, pos = 0;
pthread_mutex_init(&mutex, NULL);
for (i = 0; i < NUM_THREAD; i++) {
Func_args args;
args.data = array;
args.thread_number = i;
args.start = pos;
pos += 2;
args.end = pos;
pthread_create(&tid[i], NULL, calculate_sum, &args);
}
for (i = 0; i < NUM_THREAD; i++)
pthread_join(tid[i], NULL);
pthread_mutex_destroy(&mutex);
printf("Sum: %d\n", sum);
return 0;
}
You are passing each thread a pointer to an object that might get destroyed before the thread starts.
args is local, so it gets destroyed when the program exits the scope it's declared in - that is, at the end of the for loop body.
The thread might takes a few moments to start up, so if the thread starts after that, it will access a destroyed object - in practice, the memory will have been reused to store the next thread's values.
You can fix it by dynamically allocating the thread data with malloc (and remembering to free it in the thread or if pthread_create fails).

Squaring numbers w/ multiple threads

I'm trying to write a program that squares numbers 1-10,000 by creating 8 threads and each thread will take turns squaring ONE NUMBER EACH. Meaning that one thread will square 1, another will square 2, etc until all threads square a number. Then one thread will square 9, etc, all the way to 10,000. My code is below:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>
#include <sys/types.h>
#define NUMBER_OF_THREADS 8
#define START_NUMBER 1
#define END_NUMBER 10000
FILE *f;
void *sqrtfunc(void *tid) { //function for computing squares
int i;
for (i = START_NUMBER; i<= END_NUMBER; i++){
if ((i % NUMBER_OF_THREADS) == pthread_self()){ //if i%8 == thread id
fprintf(f, "%lu squared = %lu\n", i, i*i); //then that thread should do this
}
}
}
int main(){
//Do not modify starting here
struct timeval start_time, end_time;
gettimeofday(&start_time, 0);
long unsigned i;
f = fopen("./squared_numbers.txt", "w");
//Do not modify ending here
pthread_t mythreads[NUMBER_OF_THREADS]; //thread variable
long mystatus;
for (i = 0; i < NUMBER_OF_THREADS; i++){ //loop to create 8 threads
mystatus = pthread_create(&mythreads[i], NULL, sqrtfunc, (void *)i);
if (mystatus != 0){ //check if pthread_create worked
printf("pthread_create failed\n");
exit(-1);
}
}
for (i = 0; i < NUMBER_OF_THREADS; i++){
if(pthread_join(mythreads[i], NULL)){
printf("Thread failed\n");
}
}
exit(1);
//Do not modify starting here
fclose(f);
gettimeofday(&end_time, 0);
float elapsed = (end_time.tv_sec-start_time.tv_sec) * 1000.0f + \
(end_time.tv_usec-start_time.tv_usec) / 1000.0f;
printf("took %0.2f milliseconds\n", elapsed);
//Do not modify ending here
}
I am not sure where my error is. I create my 8 threads in main, and then depending on their thread id (tid), I want that thread to square a number. As of right now, nothing is being printed into the output file and I can't figure out why. Is my tid comparison not doing anything? Any tips are appreciated. Thanks guys.
First, you intentionally pass a parameter to each thread so it know which thread it is (from 0 to 7) That is good, but you then don't use it anymore inside the thread (this leads to one of the possible confussions you have)
Second, as you say in the explanation of how the algorithm should go, you say each thread must square a different set of numbers, but all of them do square the same set of numbers (indeed the whole set of numbers)
You have two approaches to this: Let each thread square the number, and go for the next, eight places further (so the algorithm is the one described in your explanation) or you give different sets (each 1250 consecutive numbers) and let each thread act on is own separate interval.
That said, you have to reconstruct your for loop to do one of two:
for (i = parameter; i < MAX; i += 8) ...
or
for (i = 1250*parameter; i < 1250*(parameter+1); i++) ...
that way, you'll get each thread run with a different set of input numbers.

Unix c program to calculate pi using threads

Been working on this assignment for class. Put this code together but its giving me several errors I'm not able to solve.
Code
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
//global variables
int N, T;
double vsum[T];
//pie function
void* pie_runner(void* arg)
{
double *limit_ptr = (double*) arg;
double j = *limit_ptr;
for(int i = (N/T)*j; i<=((N/T)*(j+1)-1); j++)
{
if(i %2 =0)
vsum[j] += 4/((2*j)*(2*j+1)*(2*j+2));
else
vsum[j] -= 4/((2*j)*(2*j+1)*(2*j+2));
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
if(argc != 3) {
printf("Error: Must send it 2 parameters, you sent %s", argc);
exit(1);
}
N = atoi[1];
T = atoi[2];
if(N !> T) {
printf("Error: Number of terms must be greater then number of threads.");
exit(1);
}
for(int p=0; p<T; p++) //initialize array to 0
{
vsum[p] = 0;
}
double pie = 3;
//launch threads
pthread_t tids[T];
for(int i = 0; i<T; i++)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tids[i], &attr, pie_runner, &i);
}
//wait for threads...
for(int k = 0; k<T; k++)
{
pthread_join(tids[k], NULL);
}
for(int x=0; x<T; x++)
{
pie += vsum[x];
}
printf("pi computed with %d terms in %s threads is %k\n", N, T, pie);
}
One of the problems I'm having is with the array up top. It needs to be a global variable but it keeps telling me it's not a constant, even when I declare it as such.
Any help is appreciated, with the rest of the code also.
**EDIT: After updating the code using the comments below, here is the new code. I have a few errors still there and would appreciate help dealing with them.
1) Warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] int j = (int)arg;
2)Warning: cast to pointer from integer of different size [Wint - to - pointer - cast] pthread_create(.......... , (void*)i);
NEW CODE:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
//global variables
int N, T;
double *vsum;
//pie function
void* pie_runner(void* arg)
{
long j = (long)arg;
//double *limit_ptr = (double*) arg;
//double j = *limit_ptr;
//for(int i = (j-1)*N/T; i < N*(j) /T; i++)
for(int i = (N/T)*(j-1); i < ((N/T)*(j)); i++)
{
if(i % 2 == 0){
vsum[j] += 4.0/((2*j)*(2*j+1)*(2*j+2));
//printf("vsum %lu = %f\n", j, vsum[j]);
}
else{
vsum[j] -= 4.0/((2*j)*(2*j+1)*(2*j+2));
//printf("vsum %lu = %f\n", j, vsum[j]);
}
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
if(argc != 3) {
printf("Error: Must send it 2 parameters, you sent %d\n", argc-1);
exit(1);
}
N = atoi(argv[1]);
T = atoi(argv[2]);
vsum = malloc((T+1) * sizeof(*vsum));
if(vsum == NULL) {
fprintf(stderr, "Memory allocation problem\n");
exit(1);
}
if(N <= T) {
printf("Error: Number of terms must be greater then number of threads.\n");
exit(1);
}
for(int p=1; p<=T; p++) //initialize array to 0
{
vsum[p] = 0;
}
double pie = 3.0;
//launch threads
pthread_t tids[T+1];
for(long i = 1; i<=T; i++)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tids[i], &attr, pie_runner, (void*)i);
}
//wait for threads...
for(int k = 1; k<=T; k++)
{
pthread_join(tids[k], NULL);
}
for(int x=1; x<=T; x++)
{
pie += vsum[x];
}
printf("pi computed with %d terms in %d threads is %.20f\n", N, T, pie);
//printf("pi computed with %d terms in %d threads is %20f\n", N, T, pie);
free(vsum);
}
Values not working:
./pie1 2 1
pi computed with 2 terms in 1 threads is 3.00000000000000000000
./pie1 3 1
pi computed with 3 terms in 1 threads is 3.16666666666666651864
./pie1 3 2
pi computed with 3 terms in 2 threads is 3.13333333333333330373
./pie1 4 2
pi computed with 4 terms in 2 threads is 3.00000000000000000000
./pie1 4 1
pi computed with 4 terms in 1 threads is 3.00000000000000000000
./pie1 4 3
pi computed with 4 terms in 3 threads is 3.14523809523809516620
./pie1 10 1
pi computed with 10 terms in 1 threads is 3.00000000000000000000
./pie1 10 2
pi computed with 10 terms in 2 threads is 3.13333333333333330373
./pie1 10 3
pi computed with 10 terms in 3 threads is 3.14523809523809516620
./pie1 10 4
pi computed with 10 terms in 4 threads is 3.00000000000000000000
./pie1 10 5
pi computed with 10 terms in 5 threads is 3.00000000000000000000
./pie1 10 6
pi computed with 10 terms in 6 threads is 3.14088134088134074418
./pie1 10 7
pi computed with 10 terms in 7 threads is 3.14207181707181693042
./pie1 10 8
pi computed with 10 terms in 8 threads is 3.14125482360776464574
./pie1 10 9
pi computed with 10 terms in 9 threads is 3.14183961892940200045
./pie1 11 2
pi computed with 11 terms in 2 threads is 3.13333333333333330373
./pie1 11 4
pi computed with 11 terms in 4 threads is 3.00000000000000000000
There are numerous problems with that code. Your specific problem is that, in C, variable length arrays (VLAs) are not permitted at file scope.
So, if you want that array to be dynamic, you will have to declare the pointer to it and allocate it yourself:
int N, T;
double *vsum;
and then, in main() after T has been set:
vsum = malloc (T * sizeof(*vsum));
if (vsum == NULL) {
fprintf (stderr, "Memory allocation problem\n");
exit (1);
}
remembering to free it before exiting (not technically required but good form anyway):
free (vsum);
Among the other problems:
1/ There is no !> operator in C, I suspect the line should be:
if (N > T) {
rather than:
if (N !> T) {
2/ To get the arguments from the command line, change:
N = atoi[1];
T = atoi[2];
into:
N = atoi(argv[1]);
T = atoi(argv[2]);
3/ The comparison operator is ==, not =, so you need to change:
if(i %2 =0)
into:
if (i % 2 == 0)
4/ Your error message about not having enough parameters needs to use %d rather than %s, as argc is an integral type:
printf ("Error: Must send it 2 parameters, you sent %d\n", argc-1);
Ditto for your calculation message at the end (and fixing the %k for the floating point value):
printf ("pi computed with %d terms in %d threads is %.20f\n", N, T, pie);
5/ You pass an integer pointer into your thread function but there are two problems with that.
The first is that you then extract it into a double j, which cannot be used as an array index. If it's an integer being passed in, it should be turned back into an integer.
The second is that there is no guarantee the new thread will extract the value (or even start running its code at all) before the main thread changes that value to start up another thread. You should probably just convert the integer to a void * directly rather than messing about with integer pointers.
To fix both those, use this when creating the thread:
pthread_create (&tids[i], &attr, pie_runner, (void*)i);
and this at the start of the thread function:
int j = (int) arg;
If you get warnings or experience problems with that, it's probably because your integers and pointers are not compatible sizes. In that case, you could try something like:
pthread_create (&tids[i], &attr, pie_runner, (void*)(intptr_t)i);
though I'm not sure that will work any better.
Alternatively (though it's a bit of a kludge), stick with your pointer solution and just make sure there's no possibility of race conditions (by passing a unique pointer per thread).
First, revert the thread function to receiving its value by a pointer:
int j = *((int*) arg);
Then, before you start creating threads, you need to create a thread integer array and, for each thread created, populate and pass the (address of the) correct index of that array:
int tvals[T]; // add this line.
for (int i = 0; i < T; i++) {
tvals[i] = i; // and this one.
pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_create (&tids[i], &attr, pie_runner, &(tvals[i]));
}
That shouldn't be too onerous unless you have so many threads the estra array will be problematic. But, if you have that many threads, you're going to have far greater problems.
6/ Your loop in the thread incorrectly incremented j rather than i. Since this is the same area touched by the following section, I'll correct it there.
7/ The use of integers in what is predominantly a floating point calculation means that you have to arrange your calculations so that they don't truncate divisions, such as 10 / 4 -> 2 where it should be 2.5.
That means the loop in the thread function should be changed as follows (including incrementing i as in previous point):
for (int i = j*N/T; i <= N * (j+1) / T - 1; i++)
if(i % 2 == 0)
vsum[j] += 4.0/((2*j)*(2*j+1)*(2*j+2));
else
vsum[j] -= 4.0/((2*j)*(2*j+1)*(2*j+2));
With all those changes, you get a reasonably sensible result:
$ ./picalc 100 101
pi computed with 100 terms in 101 threads is 3.14159241097198238535
Two problems with that array: The first is that T is not a compile-time constant, which it needs to be if you're programming in C++. The second is that T is initialized to zero, meaning the array will have a size of zero and all indexing of the array will be out of bounds.
You need to allocate the array dynamically once you have read T and know the size. In C you use malloc for that, in C++ you should use std::vector instead.

test "pthread_create" function behaviour

I am new in multi-threaded programming and I have a question about "pthread_create" behaviour
this is the code :
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NTHREADS 10
#define ARRAYSIZE 1000000
#define ITERATIONS ARRAYSIZE / NTHREADS
double sum=0.0, a[ARRAYSIZE];
pthread_mutex_t sum_mutex;
void *do_work(void *tid)
{
int i, k=0,start, *mytid, end;
double mysum=0.0;
mytid = (int *) tid;
start = (*mytid * ITERATIONS);
end = start + ITERATIONS;
printf ("Thread %d doing iterations %d to %d\n",*mytid,start,end-1);
for (i=start; i < end ; i++) {
a[i] = i * 1.0;
mysum = mysum + a[i];
}
sum = sum + mysum;
}
int main(int argc, char *argv[])
{
int i, start, tids[NTHREADS];
pthread_t threads[NTHREADS];
pthread_attr_t attr;
for (i=0; i<NTHREADS; i++) {
tids[i] = i;
pthread_create(&threads[i], NULL/*&attr*/, do_work, (void *) &tids[i]);
}
/* Wait for all threads to complete then print global sum */
/*
for (i=0; i<NTHREADS; i++) {
pthread_join(threads[i], NULL);
}*/
printf ("Done. Sum= %e \n", sum);
sum=0.0;
for (i=0;i<ARRAYSIZE;i++){
a[i] = i*1.0;
sum = sum + a[i]; }
printf("Check Sum= %e\n",sum);
}
the result of execution is :
Thread 1 doing iterations 100000 to 199999
Done. Sum= 0.000000e+00
Thread 0 doing iterations 0 to 99999
Thread 2 doing iterations 200000 to 299999
Thread 3 doing iterations 300000 to 399999
Thread 8 doing iterations 800000 to 899999
Thread 4 doing iterations 400000 to 499999
Thread 5 doing iterations 500000 to 599999
Thread 9 doing iterations 900000 to 999999
Thread 7 doing iterations 700000 to 799999
Thread 6 doing iterations 600000 to 699999
Check Sum= 8.299952e+11
all thread are created and the execution is not sequential (remove pthread_join), but the function do_work is executed in order and depend on thread. it means iterations 0 to 99999 are done by thread 0 and iterations 100000 to 199999 are done by thread 1 etc ...
the question is here why for example iterations 0 to 99999 is not done by thread 2 ?
This is because iteration range is calculated based on thread number from 0 to N in the following line:
start = (*mytid * ITERATIONS);
And you create and pass that number in a loop as such:
for (i=0; i<NTHREADS; i++) {
tids[i] = i;
...
In other words, 2 + N will never be 0 to perform iteration over 0 to 99999 when N is non-negative.
I think you are confused as to what threads are.
Think about each thread as its own program. If you run 10 programs at the same time, they will be running "simultaneously", i.e. instructions of these 10 programs will be interleaved, but within each program all instructions are executed in the deterministic order.
Same thing with threads. You define which numbers each thread will iterate over by passing the thread id argument when creating the thread.
You are sending the address of tids[i]th variable to thread i and printing based on it. In this case Nth thread will always print from N000000 till N999999 without any change in all the trial runs.
mytid = (int *) tid;
start = (*mytid * ITERATIONS);
end = start + ITERATIONS;
For thread 2, it would behave as,
mytid = (int *) tid; // *mytid = 2
start = ( 2 * ITERATIONS); // 2000000
end = ( 2 * ITERATIONS) + ITERATIONS; // 2999999
Thus printing 2000000 to 2999999. So you can't expect thread 2 to print 0 to 99999.
It is not wise to use global variables like sum, which are shared between threads, without any kind of locking mechanisms. They would bring unexpected results. Use of pthread_mutex here would solve this problem.

Resources