static storage with pthread functions - c

I was practicing some multithreaded programs, but I could not figure the logic behind this output.
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
int print_message(void* ptr);
int main()
{
pthread_t thread1,thread2;
char *mesg1 = "Thread 1";
char *mesg2 = "Thread 2";
int iret1, iret2;
pthread_create(&thread1, NULL, print_message, (void *)mesg1);
pthread_create(&thread2, NULL, print_message, (void *)mesg2);
pthread_join(thread1,(void*)&iret1 );
pthread_join(thread2, (void*)&iret2);
printf("Thread 1 return : %d\n", (int)iret1);
printf("Thread 2 return : %d\n", (int)iret2);
return 0;
}
int print_message(void *ptr)
{
char *mesg;
static int i=0;
mesg = (char *)ptr;
printf("%s\n",mesg);
i++;
return ((void*)i);
}
I was expecting the output
Thread 1
Thread 2
Thread 1 return : 1
Thread 2 return : 2
but I am getting the output
Thread 1
Thread 2
Thread 1 return : 0
Thread 2 return : 2
Could some please clarify this to me ? And please point if any errors in usage of pthread functions.

The variable i is shared between both threads because it is static. The behaviour of modifying a variable between multiple threads is undefined, so, in fact, both the output you get and the output you want to get are “wrong” in the sense that the compiler is under no obligation to give it to you. In fact, I was able to get the output to change depending on the optimisation level I used and it will undoubtedly be different based on the platform.
If you want to modify i, you should use a mutex:
int print_message(void *ptr)
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
char *mesg;
static int i=0;
int local_i;
mesg = (char *)ptr;
printf("%s\n",mesg);
if (pthread_mutex_lock(&mutex) == 0) {
local_i = ++i;
pthread_mutex_unlock(&mutex);
}
return ((void*)local_i);
}
If you do not use a mutex, you will never be sure to get the output you think you should get.

There are several good books on multi-threading. I found Butenhof's Programming with Posix threads quite interesting, but more recent books exist.
You may also want to read this pthreads tutorial online.
Basically, each program source code thread might not view the memory as intuitively as you expect (cache coherence, multi-processing, memory model, C11).
Practically speaking, any access to a data shared between threads should be protected by synchronization primitives, e.g. mutexes or rwlocks.
Also, note that debugging multi-threaded programs is challenging due to non-determinism and heisenbugs.

Related

pthreads in C: How can I stop the threads from interfering with each other?

I'm new to using pthreads. I want to create a program where six different threads will each output a different number. The threads can run in any order, however, each thread should run only once.
So, a possible output would be:
Thread: 5
Thread: 2
Thread: 3
Thread: 6
Thread: 1
Thread: 4
Or it could be in any other order.
#include<stdio.h>
#include<pthread.h>
void *apples(void *void_apple_num){
int *thread_num = (int *) void_apple_num;
printf("Thread: %d\n", *thread_num);
return NULL;
}
int main(){
pthread_t threads[6];
int apple_num;
for(apple_num=0; apple_num<6; apple_num++){
pthread_create(&threads[apple_num], NULL, apples, &apple_num);
}
for(apple_num=0; apple_num<6; apple_num++){
pthread_join(threads[apple_num], NULL);
}
return 0;
}
When I run the program, I have this problem of the threads interfering with each other. I am not sure if some of the threads are running twice? However, I think the problem is some of the threads are using the apple_num pointer from a different thread.
Here are two sample outputs I got:
Output 1:
Thread: 5
Thread: 0
Thread: 1
Thread: 1
Thread: 2
Thread: 2
Output 2:
Thread: 1
Thread: 4
Thread: 4
Thread: 5
Thread: 1
Thread: 1
I don't fully understand what is causing the problem. I've heard that threads can sometimes share variables? I don't know if I should use a mutex lock to somehow get the threads to run one-at-a-time.
How can I edit my code to solve this?
If somebody else has asked a similar question, please direct me to their question. I couldn't find anything when I researching.
Each of your threads gets a pointer to the very same local variable apple_num which is being changed in the loop by the main thread. Since threads start asynchronously, the value of local variable apple_num in the main thread is indeterminate from the perspective of any other thread.
You need to pass a copy of that variable to each thread.
One fix is to cast int to void* and back:
void *apples(void* apple_num){
int thread_num = (int)void_apple_num;
...
pthread_create(&threads[apple_num], NULL, apples, (void*)apple_num);
As they mention in the comments, intptr_t and uintptr_t (from <stdint.h>) may be more appropriate for round-trip without loss, e.g. uintptr_t -> void* -> uintptr_t. But C standard doesn't require any integers to round-trip to void* and back, it only requires void* -> intptr_t and back.
In a more realistic scenario, you may like to pass more than just one integer to a thread, namely, a struct. And that's the rationale for the thread start function to receive a single void* argument - it can point to an object of any data type (POSIX requires void* to also be able to store function pointers).
An example of passing a structure to a thread (without relying on implementation-defined conversion of integers to void* and back):
struct ThreadArgs {
int thread_num;
// More data members, as needed.
};
void* apples(void* arg){
struct ThreadArgs* a = arg;
printf("Thread: %d\n", a->thread_num);
free(arg);
return NULL;
}
int main() {
pthread_t threads[6];
struct ThreadArgs* a;
int apple_num;
for(apple_num=0; apple_num<6; apple_num++){
a = malloc(sizeof *a);
a->thread_num = apple_num;
pthread_create(&threads[apple_num], NULL, apples, a);
}
for(apple_num=0; apple_num<6; apple_num++)
pthread_join(threads[apple_num], NULL);
return 0;
}
Note, that you don't have to allocate the thread arguments structure on the heap (malloc). If you pass an automatic variable (on the stack) to a thread, you must make sure that the variable is unchanged and still exists when the thread accesses it. Allocating the thread arguments structure from the heap is the safest and solves this problem at the expense of malloc/free calls.

Why does thread just die if i dont set 'pthread_join'

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
int count = 0;
pthread_mutex_t MUTEX = PTHREAD_MUTEX_INITIALIZER;
void* func1(void* a){
pthread_mutex_lock(&MUTEX);
for(;count < 4;count++){
printf("LOOP 1: %d\n",count);
sleep(1);
}
pthread_mutex_unlock(&MUTEX);
}
void* func2(void* a){
pthread_mutex_lock(&MUTEX);
for(;count < 8;count++){
printf("LOOP 2: %d\n",count);
sleep(1);
}
pthread_mutex_unlock(&MUTEX);
}
int main(){
pthread_t tid[2];
int a = 1;
int status;
if(pthread_create(tid,NULL,func1,(void*)&a))
printf("func1 error\n");
if(pthread_create(tid+1,NULL,func2,(void*)&a))
printf("func2 error\n");
//pthread_join(*tid, (void *) &status);
//pthread_join(*(tid+1), (void *) &status);
}
simple code for testing how thread and mutex works.
If I run the code, it just terminates without showing anything (sometimes just one line "LOOP 1: 0")
If I uncomment
//pthread_join(*tid, (void *) &status);
//pthread_join(*(tid+1), (void *) &status);
then it works well.
HOW this happens? someone please explain
pthread_join(t,...) waits until the thread t is finished. That is to say, the ...join call does not return until t is finished.
So, your question really is about what happens in a C program if the main() function returns while threads that were created by pthread_create(...) still are running.
The answer (at least, for some versions of C)* is that after main() returns some value, v, the library then calls exit(v). You can look in the man pages or, in the documentation for whatever system you're running on to find out what else exit(...) does, but one of the things that it does is, it terminates the entire process, including all of its threads.
* I am not 100% certain that every version of C and the C standard libraries behave in this way, but it's the behavior that I am accustomed to expect.
Note also that this behavior is different from modern C++ where, std::thread instances can continue to run even after main(...) has returned.

Memory sharing between threads in C

can someone please explain exactly what memory is being shared between threads? I got the code from a website just so I can explain what I don't understand exactly. I want to know, if all the threads after they're created they will execute the function doSomeThing and will they share the same value for MyVariable or every thread will have separate values for it. (ignore the fact that there isn't any value assigned to the variable)
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
pthread_t tid[2];
void* doSomeThing(void *arg)
{
unsigned long i = 0;
int MyVariable;
pthread_t id = pthread_self();
if(pthread_equal(id,tid[0]))
{
printf("\n First thread processing\n");
}
else
{
printf("\n Second thread processing\n");
}
for(i=0; i<(0xFFFFFFFF);i++);
return NULL;
}
int main(void)
{
int i = 0;
int err;
while(i < 2)
{
err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
if (err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
else
printf("\n Thread created successfully\n");
i++;
}
return 0;
}
You've actually asked two separate questions.
what memory is being shared between threads?
Well, all memory (on typical OSes). A main difference between threads and processes is that different processes have different memory spaces, which threads within a process have the same memory space.
See also:
What is the difference between a process and a thread?
will [the two threads] share the same value for MyVariable?
No! and that's because each thread has its own stack (and their own registers state). Now, the stacks are both in the shared memory space, but each thread uses a different one.
So: Sharing memory space is not the same as sharing the value of each variable.

Threading In C: Producer Consumer taking forever to run

I'm new to concept of threading.
I was doing producer consumer problem in C but the consumer thread doesn't run when parallel with producer.
my code is as follows:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
int S;
int E;
int F;
void waitS(){
//printf("hbasd");
while(S<=0);
S--;
}
void signalS(){
S++;
}
void waitE(){
while(E<=0);
E--;
}
void signalE(){
E++;
}
void waitF(){
while(F<=0);
F--;
}
void signalF(){
F++;
}
int p,c;
void* producer(void *n){
int *j = (int *)n;
int i = *j;
while(1){
waitS();
waitE();
printf("Producer %d\n",E);
signalS();
signalF();
p++;
if(p>=i){
printf("Exiting: producer\n");
pthread_exit(0);
}
}
}
void* consumer(void *n){
int *j = (int *)n;
int i = *j;
while(1){
waitS();
waitF();
printf("Consumer %d\n",E);
signalS();
signalE();
c++;
if(c>=i){
printf("Exiting Consumer\n");
pthread_exit(0);
}
}
}
int main(int argc, char* argv[]){
int n = atoi(argv[1]);
E = n;
S = 1;
F = 0;
int pro = atoi(argv[2]);
int con = atoi(argv[3]);
pthread_t pid, cid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&pid,&attr,producer,(void *)&pro);
pthread_create(&cid,&attr,consumer,(void *)&con);
pthread_join(pid,NULL);
pthread_join(cid,NULL);
}
When i give the input as ./a.out 3 4 3
i.e n=3, pro = 4, con = 3
I get no out just an a dead lock kind of situation.
I expect an output like
Producer 2
Producer 1
Producer 0
Consumer 0
Consumer 1
Producer 0
Exiting: producer
Consumer 0
Exiting: consumer
...similar outputs where Producer runs 4 times and consumer thrice
When i give an input like ./a.out 4 4 3
i get the following output
Producer 3
Producer 2
Producer 1
Producer 0
Exiting: producer
Consumer 0
Consumer 1
Consumer 2
Exiting: consumer
from the results i'm getting a conclusion that pthread producer is executing 1st and then is pthread consumer.
I want both of them to execute simultaneously so that i get an answer similar to the first expected output when test cases like 3 4 3 are given.
You are accessing non-atomic variables from different threads without any kind of synchronization; this is a race condition and it leads to undefined behavior.
In particular, modern CPUs provide separate registers and separate caches to each CPU core, which means that if a thread running on CPU core #1 modifies the value of a variable, that modification may remain solely in CPU #1's cache for quite a while, without getting "pushed out" to RAM, and so another thread running on CPU core #2 may not "see" the thread #1's update for a long time (or perhaps never).
The traditional way to deal with this problem is either to serialize accesses to your shared variables with one or more mutexes (see pthread_mutex_init(), pthread_mutex_lock(), pthread_mutex_unlock(), etc), or use atomic variables rather than standard ints for values you want to access from multiple threads simultaneously. Both of those mechanisms have safeguards to ensure that undefined behavior won't occur (if you are using them correctly).
You can not access same memory from two different threads without synchronization. The standard for pthreads spells it out quite clearly here:
Applications shall ensure that access to any memory location by more than one thread of control (threads or processes) is restricted such that no thread of control can read or modify a memory location while another thread of control may be modifying it. Such access is restricted using functions that synchronize thread execution and also synchronize memory with respect to other threads.
Besides, even if we ignore that many CPUs don't synchronise memory unless you explicitly ask them to, your code is still incorrect in normal C because if variables can be changed behind your back they should be volatile. But even though volatile might help on some CPUs, it is incorrect for pthreads.
Just use proper locking, don't spin on global variables, there are methods to heat a room that are much cheaper than using a CPU.
In general, you should use synchronization primitives, but unlike other answerers I do believe we might not need any if we run this program on x86 architecture and prevent compiler to optimize some critical parts in the code.
According to Wikipedia, x86 architecture has almost sequential consistency, which is more than enough to implement a producer-consumer algorithm.
The rules to successfully implement such an producer-consumer algorithm is quite simple:
We must avoid writing the same variable from different threads, i.e. if one thread writes to variable X, another thread just read from X
We must tell the compiler explicitly that our variables might change somewhere, i.e. use volatile keyword on all shared between threads variables.
And here is the working example based on your code. Producer produces numbers from 5 down to 0, consumer consumes them. Please remember, this will work on x86 only due to weaker ordering on other architectures:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
volatile int P = 0;
volatile int C = 0;
volatile int value = 0;
void produce(int v)
{
value = v;
P++;
}
int consume()
{
int v = value;
C++;
return v;
}
void waitForConsumer()
{
while (C != P)
;
}
void waitForProducer()
{
while (C == P)
;
}
void *producer(void *n)
{
int i = *(int *)n;
while (1) {
waitForConsumer();
printf("Producing %d\n", i);
produce(i);
i--;
if (i < 0) {
printf("Exiting: producer\n");
pthread_exit(0);
}
}
}
void *consumer(void *n)
{
while (1) {
waitForProducer();
int v = consume();
printf("Consumed %d\n", v);
if (v == 0) {
printf("Exiting: consumer\n");
pthread_exit(0);
}
}
}
int main(int argc, char *argv[])
{
int pro = 5;
pthread_t pid, cid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&pid, &attr, producer, (void *)&pro);
pthread_create(&cid, &attr, consumer, NULL);
pthread_join(pid, NULL);
pthread_join(cid, NULL);
}
Produces the following result:
$ ./a.out
Producing 5
Producing 4
Consumed 5
Consumed 4
Producing 3
Producing 2
Consumed 3
Consumed 2
Producing 1
Producing 0
Exiting: producer
Consumed 1
Consumed 0
Exiting: consumer
For more information, I really recommend Herb Sutter's presentation called atomic<> Weapons, which is quite long, but has everything you need to know about ordering and atomics.
Despite the code listed above will work OK on x86, I really encourage you to watch the presentation above and use builtin atomics, like __atomic_load_n(), which will generate the correct assembly code on any platform.
Create new threads for producer and consumer each i.e all producers and consumers have their own threads.

Understanding pthread_detach

The following prints
In Main()
Hello World
Hello World
Why does this print Hello World twice? If I use pthread_join() the desired output occurs (only one Hello World preceeded by a In Main().
#include <pthread.h>
void *thread_func(void *arg);
int main(int argc, char **argv)
{
int s;
void *res;
pthread_t t1;
s = pthread_create(&t1, NULL, thread_func, "Hello World\n");
if (s != 0)
printf("Err\n");
printf("In Main()\n");
s = pthread_detach(t1);
if (s != 0)
printf("Err\n");
return 0;
}
void *thread_func(void *arg)
{
char *s = (char *)arg;
printf("%s", s);
pthread_exit(0);
}
I understand pthread_detach tells the library to release all of the resources utilized by the pthread once the thread is terminated... and since I terminate it at the end of thread_func, everything should be okay right?
What am I missing here?
In my opinion you are using a non-thread-safe version of the standard library (prints, fflush...). I have already seen this kind of (apparently) non-logical behavior on a old unix-like real time system. There were two different versions of std library, one for single-threaded mode and one for multithreaded. Of course, the default was single threaded...
In general, accesses to file pointers and similar things should be serialized with mutexes. In your program there are two thread terminations, each may want to call implicitly an fflush, but since the underlying buffers are not meant to be accessed concurrently, it may happen that both flushes write the same data to the output file descriptor.

Resources