pthreads - reading and writing to global variables - pthreads

I am learning about pthreads and I've created a program that creates 10 threads of which 5 read the value of a global variable and 5 update the value of a global variable. Here is some sample output from the program.
My question is why in the write() thread does it always say that the shared variable is 2 even though it is being updated each time a write() thread is created? I would of expected it to change.
Output:
Write thread - shared variable was 2 and it is now 22
Read Thread - The shared variable is 2
Write thread - shared variable was 2 and it is now 9
Write thread - shared variable was 2 and it is now 12
Write thread - shared variable was 2 and it is now 37
Write thread - shared variable was 2 and it is now 43
Read Thread - The shared variable is 2
Read Thread - The shared variable is 43
Read Thread - The shared variable is 43
Read Thread - The shared variable is 43
The code:
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#define NUM_THREADS 5
int shared_varibale = 2;
void *read(void *param);
void *write(void *param);
int main (int argc, char *argv[]) {
int i;
time_t t;
pthread_t tid[NUM_THREADS];
/* Intializes random number generator */
srand((unsigned) time(&t));
/*Create 5 write threads*/
for(i = 0; i < NUM_THREADS; i++) {
pthread_create(&tid[i], NULL, write, &shared_varibale);
}
/*Create 5 read threads*/
for(i = 0; i < NUM_THREADS; i++) {
pthread_create(&tid[i], NULL, read, &shared_varibale);
}
return 0;
}
void *read(void *param) {
int *p = (int*)param;
printf("The variable is %d\n", *p);
pthread_exit(NULL);
}
void *write(void *param) {
int *p = (int*)param;
int rand_varibale = rand() % 50;
printf("Write thread - shared variable was %d and it is now %d\n", *p, rand_varibale);
*p = rand_varibale;
pthread_exit(NULL);
}

First of all, you should not call your own functions read or write because POSIX already uses these identifiers. You should also add error checking to all function calls because it is easy to miss problems if you do not do that.
There is no synchronization in your example, so you have a data race. Among other things, this means that the threads may see an outdated value. And you do not impose any order on the execution of the threads. If your hardware supports that much parallelism, it is likely that all threads execute until the printf call (which causes all of them except one to block). Since the shared variable is only written to after the printf call, you get the results you see.

Related

passing an ofstream object to a thread function via pthread_create

I want to pass an ofstream object to a thread using pthread_create function.
Let's say I create an object like this in my main(int argc, char *argv[]) function.
ofstream file1(argv[1], fstream::out|fstream::app);
pthread_t tid;
pthread_create(&tid, NULL, function1, (void *)args);
And the function1 is defined as.
void function1(void *input)
{
ofstream file;
file = ??
file << "Hello" << endl;
}
How can I access "file1.txt" created in the main function via the file object?
There are several ways to pass the object. One would be to make it global, then then it's very straightforward for function1() to access it. Or you can pass a pointer to it as the thread's argument. Cast it to void* in the pthread_create() call and cast it back in the thread function.
void* function1(void *input) {
ofstream* file = static_cast<ofstream*>(input);
*file << "Hello" << endl;
return NULL;
}
ofstream file1("./file1.txt", fstream::out|fstream::app);
pthread_t tid;
pthread_create(&tid, NULL, function1, static_cast<void*>(&file1));
Be warned, there is a common bug that this pattern often leads to! The ofstream will be destructed when the scope it was created in ends, which is in the thread that called pthread_create(). If the thread running function1() is still running, it could use the pointer to the now destructed ofstream.
You need to insure that the ofstream remains alive until the other thread is done with it. One way would be to give it static storage duration, either as a static local variable or as a global variable. Another would to allocate it with new and then delete it in the thread that is using it. Or you could insure that the created thread is joined before the ifstream leaves scope.
Using new and delete:
void start(void) {
ofstream* file1 = new ofstream("file1.txt", fstream::app);
pthread_create(&tid, NULL, function1, static_cast<void*>(file1));
file1 = NULL; // function1 owns this now, shouldn't be used here anymore
}
void* function1(void* arg) {
ofstream* file1 = static_cast<ofstream*>(arg);
delete file1;
}
Joining before the ofstream leaves scope:
void start(void) {
{
ofstream file1("file1.txt", fstream::app);
pthread_create(&tid, NULL, function1, static_cast<void*>(file1));
// stuff
pthread_join(tid);
// now it's safe for file1 to be destructed.
}
}
Also note that the thread function should return void*, not void. Also it should be declared as extern "C" so that it will have the correct ABI when the C pthreads library calls it. Notice how in the new/delete example, I set the pointer to NULL after starting the thread. This is because you can not assume it is safe to access the ofstream from more than one thread at a time. By setting it to NULL, only the function1 thread will be able to access it.
Consider also, maybe it makes more sense to pass the name to the thread and have it open the file? This solves the issues around the lifetime of the object vs the lifetime of the thread using it.

Not able to setting thread scope.

I am learning about pthreads,I want to set the scope of a thread so for setting scope I used pthread_attr_setscope() API but when I try to get scope of a thread using pthread_attr_getscope() API it all ways return me 0 regardless what ever scope I set(either PROCESS_SCOPE/SYSTEM_SCOPE). For more information please find code below.
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
int rc;
long t;
int ret=0;
int mypolicy=-1;
int iscope=-1;
ret = pthread_attr_init (&attr);
pthread_attr_setschedpolicy(&attr,SCHED_RR);
// BOUND behavior - Creating SYSTEM_SCOPE thread
ret = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
//Unbound behaviour - Creating process scope thread
ret = pthread_attr_setscope(&attr,PTHREAD_SCOPE_PROCESS);
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
printf("Return code from pthread_create() is %d\n", rc);
printf("Return value of getschedule policy = %d \n",pthread_attr_getschedpolicy(&attr, &mypolicy));
printf("policy = %d \n",mypolicy);
printf("Return value of getscope = %d \n",pthread_attr_getscope(&attr,&iscope));
printf("scope = %d \n",iscope);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
_exit(-1);
}
}
pthread_exit(NULL);
}
I don't know why every time I get the same value of 'iscope' regardless what ever scope I set(either PROCESS_SCOPE/SYSTEM_SCOPE).
You don't check for errors in your pthread_attr_setscope calls. Put
if (ret) perror("pthread_attr_setscope");
immediately after both calls, and see what it prints. (It may be that your OS does not support one or other of the scheduling modes.)
You call pthread_attr_setscope twice in a row on the same pthread_attr_t with two different scope constants. This cannot possibly be what you want.
You need to pass the pthread_attr_t as the second argument to pthread_create, instead of the NULL you have there, for the changed setting to have any effect at all.
Once you make that change, the scheduling policy will apply to the just-created thread, but pthread_attr_getscope is being called in the main thread. Move it to PrintHello if you want to know the policy for the just-created thread.
You never used your ret variable, so the gcc compiler complained about that (I used -Wall).
Pick a scope -- you've set it twice, sequentially, as zwol mentioned
However, you don't need to use pthread_attr_getscope in the thread itself; the pthread_attr_getscope function simply reports on what's been set in the attribute.
Use pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED); - on systems that support multiple contention scopes, this call is needed to get pthread_create to honor the scheduler attribute. Otherwise, the new thread will simply inherit the main thread's scope.
If you're using Linux - Linux only supports PTHREAD_SCOPE_SYSTEM, so trying to set PTHREAD_SCOPE_PROCESS is, essentially, just ignored

pthread_join causing seg fault

As part of a pthreads tutorial exercise I wrote a program to create 10 threads than to join the 10 threads. The program runs and prints the output however it seems that on the first call to pthread_join it causes a segmentation fault. I am not sure why this is occurring. I tried searching on web, however most issues where concerning invalid pointers passed to the function. I am not sure if this is the same issue with my code, as I am not seeing it easily.
if anyone can help me, I certainly would appreciate it :)
code is below:
#include <stdio.h>
#include <pthread.h>
#define NTHREADS 10
void *thread_function(void *arg)
{
int i;
int *coming = (int*) arg;
for(i=0; i<5; i++)
printf("Hello, World (thread %d)\n", *coming);
return NULL;
}
int main(void)
{
int i;
void *exit_status;
int retVal;
pthread_t pthread_array[NTHREADS];
int randVals[10] = {23,5,17,55,9,47,69,12,71,37};
printf("threads are created\n");
for(i=0; i<10; i++)
{
retVal=pthread_create(&pthread_array[i], NULL, thread_function, &randVals[i]);
printf("pthread_create %d retVal=%d\n", i, retVal);
}
printf("threads are joined\n");
for(i=0; i<10; i++)
{
retVal= pthread_join(pthread_array[i], &exit_status);
printf("pthread_join %d retVal=%d and exit_status=%d\n", i, retVal,
*((int *)exit_status));
}
printf("all threads have ended\n");
return 0;
}
This is the problem
printf("pthread_join %d retVal=%d and exit_status=%d\n", i, retVal,
*((int *)exit_status));
your thread function returns NULL, and so this is the value stored in exit_status. So now in your printf you do this
*((int *)exit_status
you are casting this NULL pointer to a int* and then dereferencing it. Dereferencing NULL pointers is not a good idea. See this question for a fuller example of how to use exit_status What does exactly the "status" in pthread_join represent and how to query it
*((int *)exit_status));
If the thread function returns NULL (which it does), this will try to dereference it. Before doing so, you should test exit_status:
pthread_join(...);
if (exit_status != NULL)
/* Safe to use. */

what is wrong with following pthread program?

I am not able to execute pthreads program in c. Please tell me what is wrong with the following program. I am neither getting any error nor expected output.
void *worker(void * arg)
{
int i;
int *id=(int *)arg;
printf("Thread %d starts\n", *id );
}
void main(int argc, char **argv)
{
int thrd_no,i,*thrd_id,rank=0;
void *exit_status;
pthread_t *threads;
thrd_no=atoi(argv[1]-1);
thrd_id= malloc(sizeof(int)*(thrd_no));
threads=malloc(sizeof(pthread_t)*(thrd_no));
for(i=0;i<thrd_no;i++)
{
rank=i+1;
thrd_id[i]=pthread_create(&threads[i], NULL, worker, &rank);
}
for(i=0;i<thrd_no;i++)
{
pthread_join(threads[i], &exit_status);
}
}
thrd_no = atoi(argv[1] - 1); likely doesn't do what you intended; the way argv is normally passed into a new process and parsed into a C array, argv[1] - 1 is probably pointing at \0 (specifically, the \0 at the end of argv[0]). (More generally, indexing backwards off the start of a string is rarely correct.) The result is that atoi() will return 0 and no threads will be created. What did you actually intend to do there?
You are passing the same address &rank to each thread, so id and *id is the same for all your worker-s.
You should better allocate on the heap the address you pass to each worker routine.
You might also include <stdint.h and use intptr_t, e.g.
void worker (void* p)
{
intptr_t rk = (intptr_t) p;
/// etc
}
and call
intptr_t rank = i + 1;
thrd_id[i]=pthread_create(&threads[i], NULL, worker, (void*)rank);
You should learn to use a debugger and compile with all warnings and debug information, i.e. gcc -Wall -g (and improve your code till it gets no warnings, then use gdb)
code segment rank=i+1;
thrd_id[i]=pthread_create(&threads[i], NULL, worker, &rank);
will produce race condition.

how one thread can be killed in another thread

Actually,the main scenerio is that : from main thread there are two thread running.By using conditional variable,two threads will be running and sleeping and then it will return to main thread.I mean I dont want different output pattern.just one pattern:from main->thread1->thread2->main.
I have written a code for C thread.It shows the result I want sometimes and sometimes not.as for example,the output is:
I am in thread 1
before conditional wait
I am in thread 2
before conditional release
i am again in thread 2
i am again in thread 1
main exits here
The problem is sometimes "main exits here" does not execute.Please help me.It is to be noted that I cant use pthread_join().my code is given below
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
pthread_mutex_t gLock;
pthread_cond_t gCondition;
pthread_mutex_t mLock;
pthread_cond_t mCondition;
void initialize()
{
pthread_mutex_init(&gLock, NULL);
pthread_cond_init (&gCondition, NULL);
pthread_mutex_init(&mLock, NULL);
pthread_cond_init (&mCondition, NULL);
return;
}
void * threadOne(void * msg)
{
printf("%s \n",(char*) msg);
printf("before conditional wait\n");
pthread_mutex_lock(&gLock);
pthread_cond_wait(&gCondition,&gLock);
pthread_mutex_unlock(&gLock);
printf("i am again in thread 1\n");
pthread_mutex_lock(&mLock);
pthread_cond_signal(&mCondition);
pthread_mutex_unlock(&mLock);
}
void * threadTwo(void * msg)
{
printf("%s\n",(char*)msg);
printf("before conditional release\n");
pthread_mutex_lock(&gLock);
pthread_cond_signal(&gCondition);
pthread_mutex_unlock(&gLock);
printf("i am again in thread 2\n");
}
int main()
{
pthread_t thread1;
pthread_t thread2;
char * msg1="I am in thread 1";
char * msg2="I am in thread 2";
initialize();
pthread_create(&thread1,NULL,threadOne,(void*) msg1);
pthread_create(&thread2,NULL,threadTwo,(void*) msg2);
pthread_mutex_lock(&mLock);
pthread_cond_wait(&mCondition,&mLock);
pthread_mutex_unlock(&mLock);
printf("main exits here");
return 0;
}
The problem is that you are using the condition variable incorrectly. A condition variable is just a notification mechanism, not a flag. It has no internal state other than the list of threads currently waiting. Consequently, if main() has not actually executed as far as the pthread_cond_wait() call when the other threads call pthread_cond_signal() then the signal is lost, and main() will wait forever.
You need to use a separate flag associated with the condition variable. main() can then check this flag, and only wait if the flag is not set. Also, it must check this flag in a loop, to ensure that "spurious wakeups" are handled, where pthread_cond_wait() returns without a corresponding signal. The same applies to the notification between threadOne and threadTwo.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
pthread_mutex_t gLock;
pthread_cond_t gCondition;
int gFlag=0;
pthread_mutex_t mLock;
pthread_cond_t mCondition;
int mFlag=0;
void initialize()
{
pthread_mutex_init(&gLock, NULL);
pthread_cond_init (&gCondition, NULL);
pthread_mutex_init(&mLock, NULL);
pthread_cond_init (&mCondition, NULL);
}
void * threadOne(void * msg)
{
printf("%s \n",(char*) msg);
printf("before conditional wait\n");
pthread_mutex_lock(&gLock);
while(!gFlag)
{
pthread_cond_wait(&gCondition,&gLock);
}
pthread_mutex_unlock(&gLock);
printf("i am again in thread 1\n");
pthread_mutex_lock(&mLock);
mFlag=1;
pthread_cond_signal(&mCondition);
pthread_mutex_unlock(&mLock);
}
void * threadTwo(void * msg)
{
printf("%s\n",(char*)msg);
printf("before conditional release\n");
pthread_mutex_lock(&gLock);
gFlag=1;
pthread_cond_signal(&gCondition);
pthread_mutex_unlock(&gLock);
printf("i am again in thread 2\n");
}
int main()
{
pthread_t thread1;
pthread_t thread2;
char * msg1="I am in thread 1";
char * msg2="I am in thread 2";
initialize();
pthread_create(&thread1,NULL,threadOne,(void*) msg1);
pthread_create(&thread2,NULL,threadTwo,(void*) msg2);
pthread_mutex_lock(&mLock);
while(!mFlag)
{
pthread_cond_wait(&mCondition,&mLock);
}
pthread_mutex_unlock(&mLock);
printf("main exits here");
return 0;
}

Resources