Search code examples
multithreadingpthreadsround-robin

Running multiple thread with round-robin scheduling


I'm quite new to multi-threading programming. I want to write a code with 3 different threads, each of which prints some different characters. The execution of the threads should be based on a round-robin algorithm. Suppose we have t1, t2, and t3 threads, their execution sequence should be like t1, t2, t3, t1, t2, t3,...

I write the following code for this purpose:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sched.h>

void* a(void* ptr) {
    for (int i=0; i< 10; i++){
        printf("1");
        printf("2");
        printf("3");
        printf("4");
    }
    return NULL;
}

void* b(void* ptr) {
    for (int i=0; i< 10; i++){
        printf("a");
        printf("b");
        printf("c");
        printf("d");
    }
    return NULL;
}

void* c(void* ptr) {
    for (int i=0; i< 10; i++){
        printf("5");
        printf("6");
        printf("7");
        printf("8");
    }
    return NULL;
}

int main() {
    pthread_attr_t attr1, attr2, attr3;
    
    pthread_attr_init(&attr1);
    pthread_attr_init(&attr2);
    pthread_attr_init(&attr3);
    
    pthread_t t1, t2, t3;
    
    pthread_attr_setschedpolicy(&attr1, SCHED_RR);
    pthread_create(&t1, &attr1, a, NULL);
    
    pthread_attr_setschedpolicy(&attr2, SCHED_RR);
    pthread_create(&t2, &attr2, b, NULL);
    
    pthread_attr_setschedpolicy(&attr3, SCHED_RR);
    pthread_create(&t3, &attr3, c, NULL);
    
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_join(t3, NULL);
    
    pthread_exit(0);
    return 0;
}

And the output is:

First of all: the output is not reproducible, every time I run the binary file I get different output.

12341234123412341234156785678567856785678567856785678567856782341234123412341234abcdabcdabcdabcdabcdabcdabcdabcdabcdabcd.

My desired output is something like this:

123abc567...

Does everybody know what the problem is with my code?

Thanks


Solution

  • How can I ensure that my threads are being executed in the Round-robin scheduling policy?

    You're almost there. You ensure it by calling pthread_attr_setschedpolicy(..., SCHED_RR); but then, you need to check the return value to see if it actually worked:

    pthread_attr_t attr1;
    int rVal = pthread_attr_setschedpolicy(&attr1, SCHED_RR);
    if (rVal != 0) {
        // Failed to set the desired scheduler policy.
        perror("pthread_attr_setschedpolicy(&attr1, SCHED_RR)");
        exit(1);
    }
    
    rVal = pthread_create(&t1, &attr1, a, NULL);
    if (rVal != 0) {
        // Failed to create a new thread.
        perror("pthread_create(&t1, &attr1, a, NULL)");
        exit(1);
    }
    

    What I want is...one iteration of 1234 followed by one iteration of abcd followed by one iteration of 5678 and repeat.

    Well, that's the real problem. "Round-robin" does not mean what you seem to think it means. In fact, There is no scheduler policy that you can set that will make your program produce that output. If you want the threads to cooperate with each other in that way, then you'll need to write explicit code to make them communicate with each other. You need each thread's for loop to;

    1. Await a message/signal/event that means, "It's your turn,"
    2. Print it's thing,
    3. Send a message/signal/event to the next thread,
    4. Go back to step 1.

    Then, after your main thread has created each of the three new threads, it needs to kick the whole thing off by telling any one of the new threads, "it's your turn."

    I would use a semaphore as the means by which one thread tells another, "It's your turn." I would have one semaphore per thread, and I would pass pointers to two semaphores in to each thread: The one that the thread awaits to await its turn, and the one that the thread signals to let the next thread run.

    Illustration of the relationship between the semaphores and the threads

    Unfortunately, the Posix Threads Library (pthreads) doesn't provide any easy-to-use semaphore, and Unix semaphores aren't exactly trivial to use.

    IMO, you should do a little research, and then come back and ask a new question if you encounter anything that you don't understand.