variable in thread callstack changing unexpectedly c - c

Using c11 threads, I'm trying to ensure that foo is thread safe. While foo isn't reentrant, I'm trying to mitigate this with mutexes.
I don't understand why the value of thrdn is changing in the critical loop. My understanding was that each threaded call to foo would have its own version of thrdn, but it seems that it is being modified by other threads at run-time.
I've tried moving the mtx_lock above thrdn's declaration and changing thrdn to be of type atomic_int * however these both result in the same behaviour.
#include <stdio.h>
#include <threads.h>
#include <string.h>
#include <stdlib.h>
#define THREAD_MAX 5
thrd_t threads[THREAD_MAX];
mtx_t mtx;
void foo(void * data)
{
int* thrdn = (int *)data;
mtx_lock(&mtx);
for(int i = 0; i < 3; ++i) {
printf("thread %d, number %d\n", *thrdn, i);
}
mtx_unlock(&mtx);
}
int main()
{
mtx_init(&mtx, mtx_plain | mtx_recursive);
for(int i = 0; i < THREAD_MAX; ++i){
thrd_create(&threads[i], foo, &i);
}
for(int i = 0; i < THREAD_MAX; ++i){
thrd_join(threads[i], NULL);
}
mtx_destroy(&mtx);
}

As has been noted in the comments, the issue was the reference to the local variable i. Tracking thread ids separately as seen in this answer solved the issue.

Related

different number of thread is created

I am learning pthread and i am using vs code to run the c code.
As per the vs code docs, i installed MSY2S2 MSY and it is installed.
when i run this code:
#include <stdio.h>
#include<stdlib.h>
#include <pthread.h>
void *bin_finding(void *p){
int* ptr = (int*)p;
printf("%d", *ptr);
// printf("%s", "hello");
}
int main(){
int data_count = 10;
int num_of_thread = 4;
int equalDivisionCount = data_count/num_of_thread;
int excessCount = data_count%num_of_thread;
int indexCount[num_of_thread];
int i;
pthread_t tid[num_of_thread];
for(i=0; i<4; i++){
indexCount[i] = i;
pthread_create(&tid[i], NULL, bin_finding, &indexCount[i]);
}
return 0;
}
when i click run and debug in left most option, it gives different result everytime.
sometime i get 0
sometime 01
sometime 0123
so slmost every run is different and most common is 0.
if anybody, please help me in this.
Your program is exiting before all threads of execution get a chance to finish.
Use a second loop, after the first, containing calls to pthread_join to wait for each of your threads to fully execute:
for (int i = 0; i < num_of_thread; i++)
pthread_join(tid[i], NULL);

Threads in C interrupt each other

So i have a global variable called counter and i run 4 threads which increment in million times but the result i am getting at the end does not even reach 2 million.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
int nthread;
int counter=0;
void *f(void *arg)
{
int i = *(int *)arg;
int *p;
for (int c = 0; c < 1000000; c++)
{
counter++;
}
printf(" I am thread %d (out of %d),tid =% ld\n", i, nthread, pthread_self());
p = malloc(sizeof(int));
*p = i * 2;
pthread_exit(p); // return p
}
int main(int argc, char *argv[])
{
pthread_t *tid;
int e, i, *ti;
nthread = 4;
tid = malloc(nthread * sizeof(pthread_t));
ti = malloc(nthread * sizeof(int));
for (i = 0; i < nthread; i++)
{
ti[i] = i;
if ((e = pthread_create(&tid[i], NULL, f, &ti[i])) != 0)
send_error(e, " pthread_create ");
}
for (i = 0; i < nthread; i++)
{
void *r;
if ((e = pthread_join(tid[i], &r)) != 0)
send_error(e, " pthread_join ");
printf(" Return of thread %d = %d\n", i, *(int *)r);
free(r);
}
printf("counter is %d\n",counter);
free(tid);
free(ti);
}
What causes this and how i can fix this?
PS:if your code not compile replace send_error with printfs
The pthreads standards is very clear that you may not access an object in one thread while another thread is, or might be, modifying it. Your code violates this rule.
There are many reasons for this rule, but the most obvious is this:
for (int c = 0; c < 1000000; c++)
{
counter++;
}
You want your compiler to optimize code like this. You want it to keep counter in a register or even eliminate the loop if it can. But without the requirement that you avoid threads overlapping modifications and accesses to the same object, the compiler would have to somehow prove that no other code in any other thread could touch counter while this code was running.
That would result in a huge amount of valuable optimizations being impossible on the 99% of code that doesn't share objects across threads just because the compiler can't prove that accesses might overlap.
It makes much more sense to require code that does have overlapping object access to clearly indicate that they do. And every threading standard provides good ways to do this, including pthreads.
You can use any method to prevent this problem that you like. Using a mutex is the simplest and definitely the one you should learn first.

Fill array with multiple threads in C

I have the following code of filling an array with multiple threads:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define MAX_ITEMS 67108864
#define LINES_PER_THREAD 8388608
#define THREADS 8
static int *array;
static pthread_t pids[THREADS];
static int args[THREADS];
static void init_array_line(int *line) {
int i, max;
i = *line;
max = i + LINES_PER_THREAD;
for (i; i < max; i++)
array[i] = rand() % 10000 + 1;
}
static void init_array() {
int i;
for ( i = 0; i < THREADS; i++) {
args[i]=i* LINES_PER_THREAD;
pthread_create(pids + i, NULL, &init_array_line, args + i);;
}
}
static wait_all() {
for (int i = 0; i < THREADS; i++) {
pthread_join(pids[i], NULL);
}
}
int
main(int argc, char **argv)
{
array = (int *)malloc(MAX_ITEMS * sizeof(int));
init_array();
wait_all();
}
I am giving each thread 1/8 of the array to fill LINES_PER_THREAD, but it seems that it takes longer than filling it normally. Any suggestions why might this be?
I suspect the main bottleneck would the calls to rand(). rand() isn't required to be thread-safe. So, it can't be safely used in a multi-threaded program when multiple threads could call rand() concurrently. But the Glibc implementation uses an internal lock to protect against such uses. This effectively serializes the call to rand() in all threads and thus severely affecting the multi-threaded nature of your program. Instead use rand_r() which doesn't need to maintain any internal state (because the caller(s) do) and can at least solve this aspect of your problem.
In general, if the threads don't do sufficient work then the thread creation/synchronization overhead can outdo the concurrency that could be available on multi-core systems using threads.

Unexpected results from passing int-value in multithreading, C

I am currently trying to learn about multi-threading in C. But I have got very unexpected results which have left me stumped. In this program, I am trying to fill up a matrix by using threads. I am creating 1024 threads, passing the i value into the function. Then I proceed to use it.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define SIZE 1024
static double a[SIZE][SIZE];
static double b[SIZE][SIZE];
static double c[SIZE][SIZE];
void*
init_matrix(void* msg)
{
int j;
int num = *((int*) msg);
printf("%d\n", num);
for (j = 0; j < SIZE; j++) {
a[num][j] = drand48();
b[num][j] = drand48();
}
pthread_exit(NULL);
}
int
main(int argc, char **argv)
{
//Init threads
pthread_t p_initThreads[SIZE];
int i,j;
for(i = 0; i< SIZE; i++)
{
pthread_create(&p_initThreads[i], NULL, init_matrix, (void*)&i);
}
for(j = 0; j<SIZE; j++)
{
pthread_join(p_initThreads[j], NULL);
}
}
Expected results from the prinf would be; 1-2-3-4-5-6-7-8-9-10. With the possible
result of it being inorder due to of it being in threads. But the reults on my computer is this;
1-2-2-4-5-7-24-25-25-25-25-25-25-25-25-25-25-25-25-25-25-25-25-25-25-26-35-36-36-37-37-37-37-37-37-37-37-38-39-40
By commentating out;
for (j = 0; j < SIZE; j++) {
a[num][j] = drand48();
b[num][j] = drand48();
}
I get the result that I want. Why is that? It should not do anything to num!
You are passing the address of i as the input parameter of the thread. If you were passing the value of i, you would get 1-2-3-4-5-... . But when you pass the address, it is entirely possible that before the printf line is executed, the main thread already incremented i. And printf displays the current value of i, not the value it had at the moment of thread creation.
What you have is a race condition with multiple threads accessing the same memory location (variable i) since you are passing the address of i to all threads.
What you really wanted to do was pass the value of i. Call the pthread_create() with:
pthread_create(&p_initThreads[i], NULL, init_matrix, (void*)i);
and read the value as:
int num = (int) msg;
instead of : int num = *((int*) msg);
You should also check if pthread_create() returns non-zero for failures. If that's the case, you are not going to get expected results.

How can I initiate an array, each element in a separate thread

I am trying to create an array of size n (where n is user's input) and when the user runs the program, the array elements should be set to 1 (each in a separate thread). Here is what I have done so far:
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <process.h>
int *x;
DWORD WINAPI init_X(LPVOID param)
{
int index = *(int *) param;
x[index] = 1;
return 0;
}
int main(int argc, char *argv[])
{
int n = atoi(argv[1]);
int i; // counter.
HANDLE THandles[n];
x = malloc(n * sizeof (int));
for(i = 0; i < n; i++)
{
THandles[i] = CreateThread(NULL, 0, init_X, &i, 0, NULL);
}
// Now wait for threads to finish
WaitForMultipleObjects(n, THandles, TRUE, INFINITE);
// Close the thread handle
for(i = 0; i < n; i++)
{
CloseHandle(THandles[i]);
}
printf("After initialization x = ");
for(i = 0; i < n; i++)
{
printf("%d ", x[i]);
if(i < n - 1) printf(" ");
}
// ...
return 0;
}
I run this program and I got wrong outputs:
> Test.exe 3
After initialization x = 11611536 11600064 50397186
It should be After initialization x = 1 1 1 though. I am not sure how I can I fix this, but I am sure its something related to the pointers.
P.S: I'm Java programmer so I'm not familiar with pointers.
The value you are passing as your array index will more than likely be invalid by the time the thread runs, as there is no guaranteeing that the thread is run immediately after the call to CreateThread.
You have two solutions, either pass by value (simple & easy, but not always safe) or allocate a temporary buffer for the value that will be freed by the thread when its used.
Minor Update:
In fact, a better way would be to pass &x[i], then you can just do *(int*)param = 1;
You are passing i by pointer to the thread, so the value each thread gets will depend on when int index = *(int *) param; actually executes and it should be something between 0 and n. You can just pass i by value (casted to a pointer) to avoid this.

Resources