1195. Fizz Buzz Multithreaded

You have the four functions:

  • printFizz that prints the word “fizz” to the console,
  • printBuzz that prints the word “buzz” to the console,
  • printFizzBuzz that prints the word “fizzbuzz” to the console, and
  • printNumber that prints a given integer to the console.

You are given an instance of the class FizzBuzz that has four functions: fizz, buzz, fizzbuzz and number. The same instance of FizzBuzz will be passed to four different threads:

  • Thread A: calls fizz() that should output the word “fizz”.
  • Thread B: calls buzz() that should output the word “buzz”.
  • Thread C: calls fizzbuzz() that should output the word “fizzbuzz”.
  • Thread D: calls number() that should only output the integers.

Modify the given class to output the series [1, 2, “fizz”, 4, “buzz”, …] where the i t h i^{th} ith token (1-indexed) of the series is:

  • “fizzbuzz” if i is divisible by 3 and 5,
  • “fizz” if i is divisible by 3 and not 5,
  • “buzz” if i is divisible by 5 and not 3, or
  • i if i is not divisible by 3 or 5.

Implement the FizzBuzz class:

  • FizzBuzz(int n) Initializes the object with the number n that represents the length of the sequence that should be printed.
  • void fizz(printFizz) Calls printFizz to output “fizz”.
  • void buzz(printBuzz) Calls printBuzz to output “buzz”.
  • void fizzbuzz(printFizzBuzz) Calls printFizzBuzz to output “fizzbuzz”.
  • void number(printNumber) Calls printnumber to output the numbers.
     
Example 1:

Input: n = 15
Output: [1,2,“fizz”,4,“buzz”,“fizz”,7,8,“fizz”,“buzz”,11,“fizz”,13,14,“fizzbuzz”]

Example 2:

Input: n = 5
Output: [1,2,“fizz”,4,“buzz”]

Constraints:
  • 1 <= n <= 50

From: LeetCode
Link: 1195. Fizz Buzz Multithreaded


Solution:

Ideas:
  • Maintain a shared counter cur.
  • Use four semaphores, one for each thread.
  • Initially semNumber = 1 because sequence starts at 1.
  • After a thread prints its value, it increments cur and signals the semaphore corresponding to the next value.
  • When cur > n, wake all waiting threads so they can exit cleanly.
Code:
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

typedef struct {
    int n;
    int cur;

    sem_t semFizz;
    sem_t semBuzz;
    sem_t semFizzBuzz;
    sem_t semNumber;

    pthread_mutex_t mutex;
} FizzBuzz;

FizzBuzz* fizzBuzzCreate(int n) {
    FizzBuzz* obj = (FizzBuzz*)malloc(sizeof(FizzBuzz));

    obj->n = n;
    obj->cur = 1;

    sem_init(&obj->semFizz, 0, 0);
    sem_init(&obj->semBuzz, 0, 0);
    sem_init(&obj->semFizzBuzz, 0, 0);
    sem_init(&obj->semNumber, 0, 1);

    pthread_mutex_init(&obj->mutex, NULL);

    return obj;
}

// Don't change the following declarations
void printNumber(int a);
void printFizz();
void printBuzz();
void printFizzBuzz();

static void nextTurn(FizzBuzz* obj) {
    if (obj->cur > obj->n) {
        sem_post(&obj->semFizz);
        sem_post(&obj->semBuzz);
        sem_post(&obj->semFizzBuzz);
        sem_post(&obj->semNumber);
        return;
    }

    if (obj->cur % 15 == 0)
        sem_post(&obj->semFizzBuzz);
    else if (obj->cur % 3 == 0)
        sem_post(&obj->semFizz);
    else if (obj->cur % 5 == 0)
        sem_post(&obj->semBuzz);
    else
        sem_post(&obj->semNumber);
}

// printFizz() outputs "fizz".
void fizz(FizzBuzz* obj) {
    while (1) {
        sem_wait(&obj->semFizz);

        pthread_mutex_lock(&obj->mutex);

        if (obj->cur > obj->n) {
            pthread_mutex_unlock(&obj->mutex);
            break;
        }

        printFizz();
        obj->cur++;

        nextTurn(obj);

        pthread_mutex_unlock(&obj->mutex);
    }
}

// printBuzz() outputs "buzz".
void buzz(FizzBuzz* obj) {
    while (1) {
        sem_wait(&obj->semBuzz);

        pthread_mutex_lock(&obj->mutex);

        if (obj->cur > obj->n) {
            pthread_mutex_unlock(&obj->mutex);
            break;
        }

        printBuzz();
        obj->cur++;

        nextTurn(obj);

        pthread_mutex_unlock(&obj->mutex);
    }
}

// printFizzBuzz() outputs "fizzbuzz".
void fizzbuzz(FizzBuzz* obj) {
    while (1) {
        sem_wait(&obj->semFizzBuzz);

        pthread_mutex_lock(&obj->mutex);

        if (obj->cur > obj->n) {
            pthread_mutex_unlock(&obj->mutex);
            break;
        }

        printFizzBuzz();
        obj->cur++;

        nextTurn(obj);

        pthread_mutex_unlock(&obj->mutex);
    }
}

// You may call global function `void printNumber(int x)`
// to output "x", where x is an integer.
void number(FizzBuzz* obj) {
    while (1) {
        sem_wait(&obj->semNumber);

        pthread_mutex_lock(&obj->mutex);

        if (obj->cur > obj->n) {
            pthread_mutex_unlock(&obj->mutex);
            break;
        }

        printNumber(obj->cur);
        obj->cur++;

        nextTurn(obj);

        pthread_mutex_unlock(&obj->mutex);
    }
}

void fizzBuzzFree(FizzBuzz* obj) {
    sem_destroy(&obj->semFizz);
    sem_destroy(&obj->semBuzz);
    sem_destroy(&obj->semFizzBuzz);
    sem_destroy(&obj->semNumber);

    pthread_mutex_destroy(&obj->mutex);

    free(obj);
}
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐