Hone logo
Hone
Problems

M:N Threading in Go

M:N threading, also known as multiplexed threading, is a threading model where multiple processes can be mapped to a smaller number of threads. This is in contrast to 1:1 threading where each process has its own thread. This challenge asks you to implement a simplified version of M:N threading in Go, allowing multiple worker processes to be handled by a pool of worker threads. This is useful for scenarios where you want to efficiently utilize system resources and handle a large number of concurrent tasks without creating an excessive number of threads.

Problem Description

You are tasked with creating a system that simulates M:N threading. The system will consist of:

  1. Process Pool: A pool of processes, each representing a unit of work to be done. Each process will have a unique ID (integer).
  2. Thread Pool: A pool of threads that will execute the processes.
  3. Dispatcher: A component that assigns processes from the process pool to available threads in the thread pool.

The goal is to design and implement this system in Go. The dispatcher should continuously assign processes to threads until all processes are completed. Threads should execute the assigned process and then become available for new assignments. The system should handle multiple processes concurrently.

Key Requirements:

  • Concurrency: Processes should be executed concurrently.
  • Thread Pool Management: Threads should be managed efficiently, avoiding unnecessary thread creation.
  • Process Assignment: Processes should be assigned to threads in a fair and timely manner.
  • Completion Tracking: The system should track the completion status of each process.
  • Error Handling: Handle potential errors gracefully (e.g., thread panics).

Expected Behavior:

The system should take a list of process IDs as input. Each process ID represents a unit of work. The dispatcher should assign these processes to the thread pool for execution. Once a thread completes a process, it should become available to handle another process. The system should print the process ID and the thread ID that executed it. Finally, it should print a message indicating that all processes have been completed.

Edge Cases to Consider:

  • Empty Process List: Handle the case where the input list of process IDs is empty.
  • More Processes than Threads: Ensure that all processes are eventually executed even if there are more processes than threads.
  • Thread Panics: Handle panics within threads gracefully to prevent the entire system from crashing.
  • Large Number of Processes: Consider the scalability of the system with a very large number of processes.

Examples

Example 1:

Input: [1, 2, 3, 4, 5]
Output:
Thread 1: Process 1
Thread 2: Process 2
Thread 1: Process 3
Thread 2: Process 4
Thread 1: Process 5
All processes completed.

Explanation: Processes are assigned to two threads (Thread 1 and Thread 2). The order of execution may vary depending on thread scheduling, but all processes will be executed.

Example 2:

Input: []
Output:
All processes completed.

Explanation: The input list is empty, so no processes are executed.

Example 3:

Input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Thread Pool Size: 3
Output: (Order may vary)
Thread 1: Process 1
Thread 2: Process 2
Thread 3: Process 3
Thread 1: Process 4
Thread 2: Process 5
Thread 3: Process 6
Thread 1: Process 7
Thread 2: Process 8
Thread 3: Process 9
Thread 1: Process 10
All processes completed.

Explanation: With a thread pool size of 3, the processes are distributed among the three threads.

Constraints

  • The number of processes (M) can be up to 1000.
  • The number of threads (N) can be up to 10.
  • Process IDs are positive integers.
  • The system should complete all processes within a reasonable time (e.g., less than 5 seconds).
  • Error handling should prevent panics from crashing the entire system.

Notes

  • You can use Go's sync.WaitGroup to track the completion of threads.
  • Consider using channels to communicate between the dispatcher and the threads.
  • The "work" performed by each process can be simulated by a simple sleep function. The duration of the sleep can be random to simulate varying process execution times.
  • Focus on the core M:N threading logic; detailed error handling and logging are not required for this challenge, but should be considered.
  • The output format is flexible, but should clearly indicate which thread executed which process.
  • Think about how to handle thread panics to prevent the entire system from crashing. A recover() call within the thread's execution function is a good approach.
Loading editor...
go