0

I want to print numbers using two threads T1 and T2. T1 should print numbers like 1,2,3,4,5 and then T2 should print 6,7,8,9,10 and again T1 should start and then T2 should follow. It should print from 1....100. I have two questions.

  1. How can I complete the task using threads and one global variable?
  2. How can I schedule threads in desired order in linux?
StefanM
  • 797
  • 1
  • 10
  • 17
MD GHOUSE
  • 7
  • 2
  • 2
    Possible duplicate of [C Threaded Programming - Incrementing a shared variable](http://stackoverflow.com/questions/1533390/c-threaded-programming-incrementing-a-shared-variable) – LPs Oct 17 '16 at 06:24

3 Answers3

1

How can I schedule threads in desired order in linux?

You need to use locking primitives, such as mutexes or condition variables to influence scheduling order of threads. Or you have to make your threads work independently on the order.

How can I complete the task using threads and one global variable?

If you are allowed to use only one variable, then you can't use mutex (it will be the second variable). So the first thing you must do is to declare your variable atomic. Otherwise compiler may optimize your code in such a way that one thread will not see changes made by other thread. And for such simple code that you want, it will do so by caching variable on register. Use std::atomic_int. You may find an advice to use volatile int, but nowdays std::atomic_int is a more direct approach to specify what you want.

You can't use mutexes, so you can't make your threads wait. They will be constantly running and wasting CPU. But that's seems OK for the task. So you will need to write a spinlock. Threads will wait in a loop constantly checking the value. If value % 10 < 5 then first thread breaks the loop and does incrementing, otherwise second thread does the job.

Because the question looks like a homework I don't show here any code samples, you need to write them yourself.

Alexey Guseynov
  • 5,116
  • 1
  • 19
  • 29
1

1: the easiest way is to use mutexes. this is a basic implementation with a unfair/undefined sheduling

int counter=1;
pthread_mutex_t mutex; //needs to be initialised

void incrementGlobal() {
    for(int i=0;i<5;i++){
        counter++;
        printf("%i\n",counter);
    }
 }

T1/T2:

pthread_mutex_lock(&mutex);
incrementGlobal();
pthread_mutex_unlock(&mutex);

2: the correct order can be archieved with conditional-variables: (but this needs more global-variables)

global:

int num_thread=2;
int current_thread_id=0;
pthread_cond_t cond; //needs to be initialised

T1/T2:

int local_thread_id; // the ID of the thread
while(true) {
    phread_mutex_lock(&mutex);
    while (current_thread_id != local_thread_id) {
        pthread_cond_wait(&cond, &mutex);
    }
    incrementGlobal();
    current_thread_id = (current_thread_id+1) % num_threads; 
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&mutex);
}
Domso
  • 970
  • 1
  • 10
  • 22
0

How can I complete the task using threads and one global variable?

If you are using Linux, you can use POSIX library for threading in C programming Language. The library is <pthread.h>. However, as an alternative, a quite portable and relatively non-intrusive library, well supported on gcc and g++ and (with an old version) on MSVC is openMP.

It is not standard C and C++, but OpenMP itself is a standard.

How can I schedule threads in desired order in linux?

To achieve your desired operation of printing, you need to have a global variable which can be accessed by two threads of yours. Both threads take turns to access the global variable variable and perform operation (increment and print). However, to achieve desired order, you need to have a mutex. A mutex is a mutual exclusion semaphore, a special variant of a semaphore that only allows one locker at a time. It can be used when you have an instance of resource (global variable in your case) and that resource is being shared by two threads. A thread after locking that mutex can have exclusive access to an instance of resource and after completing it's operation, a thread should release the mutex for other threads.

You can start with threads and mutex in <pthread.h> from here.

The one of the possible solution to your problem could be this program is given below. However, i would suggest you to find try it yourself and then look at my solution.

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t lock;
int variable=0;

#define ONE_TIME_INC 5
#define MAX 100

void *thread1(void *arg)
{
 while (1) {
    pthread_mutex_lock(&lock);
    printf("Thread1: \n");
    int i;
    for (i=0; i<ONE_TIME_INC; i++) {
        if (variable >= MAX)
            goto RETURN;
        printf("\t\t%d\n", ++variable);
    }   
    printf("Thread1: Sleeping\n");
    pthread_mutex_unlock(&lock);
    usleep(1000);
}
RETURN:
pthread_mutex_unlock(&lock);
return NULL;
}

void *thread2(void *arg)
{
while (1) {
    pthread_mutex_lock(&lock);
    printf("Thread2: \n");
    int i;
    for (i=0; i<ONE_TIME_INC; i++) {
        if (variable >= MAX)
            goto RETURN;
        printf("%d\n", ++variable);
    }   
    printf("Thread2: Sleeping\n");
    pthread_mutex_unlock(&lock);
    usleep(1000);
}
RETURN:
pthread_mutex_unlock(&lock);
return NULL;

}

int main()
{

if (pthread_mutex_init(&lock, NULL) != 0) {
    printf("\n mutex init failed\n");
    return 1;
}

pthread_t pthread1, pthread2;
if (pthread_create(&pthread1, NULL, thread1, NULL))
    return -1;
if (pthread_create(&pthread2, NULL, thread2, NULL))
    return -1;

pthread_join(pthread1, NULL);
pthread_join(pthread2, NULL);

pthread_mutex_destroy(&lock);

return 0;
}
abhiarora
  • 9,743
  • 5
  • 32
  • 57