Skip to content

ProducerConsumer - five variants of the producer/consumer pattern#6

Merged
hakenr merged 2 commits into
masterfrom
claude/adoring-chebyshev-1082a2
Apr 29, 2026
Merged

ProducerConsumer - five variants of the producer/consumer pattern#6
hakenr merged 2 commits into
masterfrom
claude/adoring-chebyshev-1082a2

Conversation

@hakenr

@hakenr hakenr commented Apr 29, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a new ProducerConsumer learning project that walks through the producer/consumer pattern from a naive racy implementation up to a modern Channel<T>-based solution. Each variant is a standalone net10.0 console app, all collected under a single .slnx solution.

What's included

  • README.md — task description, goals, questions for each variant, and notes (Czech).
  • ProducerConsumer.slnx — multi-project solution.
  • Five console apps, each a single Program.cs with top-level statements:
    1. ProducerConsumer.Naive — shared Queue<int> without synchronization. Intentionally buggy: race conditions and busy waiting.
    2. ProducerConsumer.Lock — atomic enqueue/dequeue via lock. Still busy waits.
    3. ProducerConsumer.MonitorWaitMonitor.Wait / Monitor.Pulse; consumer sleeps when the queue is empty. Uses while (not if) to handle spurious wakeups; finished flag + PulseAll for shutdown.
    4. ProducerConsumer.AsyncSemaphore — async consumer using SemaphoreSlim.WaitAsync() so the waiting thread is freed up.
    5. ProducerConsumer.Channel — modern solution using System.Threading.Channels and await foreach, with Writer.Complete() for shutdown.

Each variant produces N=20 items so the producer/consumer interleaving is visible in the console output.

Test plan

  • dotnet build ProducerConsumer/ProducerConsumer.slnx — succeeds, 0 warnings, 0 errors.
  • All five variants run end-to-end and print items 1..20 as expected.
  • Reviewer skim: README content matches the assignment text verbatim; comments in each Program.cs are aligned with the matching README section.

🤖 Generated with Claude Code

Adds a learning project covering the producer/consumer pattern from a
naive racy implementation up to a modern Channel<T>-based solution.
Each variant is a standalone net10.0 console app sharing a single
.slnx solution.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 29, 2026 11:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new ProducerConsumer learning project to the repo, showcasing five producer/consumer implementations from a deliberately broken baseline through progressively better synchronization approaches up to Channel<T>, bundled in a single .slnx solution.

Changes:

  • Added ProducerConsumer/README.md assignment text (Czech) describing goals and questions for each variant.
  • Added ProducerConsumer/ProducerConsumer.slnx solution aggregating five standalone console projects.
  • Added five net10.0 console apps (Naive, Lock, MonitorWait, AsyncSemaphore, Channel) demonstrating different synchronization techniques.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
ProducerConsumer/README.md Documents the assignment, goals, and questions for each implementation variant.
ProducerConsumer/ProducerConsumer.slnx New solution file grouping the five demo projects plus README.
ProducerConsumer/ProducerConsumer.Naive/Program.cs Intentionally racy/busy-wait baseline implementation.
ProducerConsumer/ProducerConsumer.Naive/ProducerConsumer.Naive.csproj New console project for the naive variant.
ProducerConsumer/ProducerConsumer.Lock/Program.cs lock-protected queue access (still busy waiting).
ProducerConsumer/ProducerConsumer.Lock/ProducerConsumer.Lock.csproj New console project for the lock variant.
ProducerConsumer/ProducerConsumer.MonitorWait/Program.cs Uses Monitor.Wait/Pulse to remove busy waiting and handle shutdown.
ProducerConsumer/ProducerConsumer.MonitorWait/ProducerConsumer.MonitorWait.csproj New console project for the Monitor variant.
ProducerConsumer/ProducerConsumer.AsyncSemaphore/Program.cs Async consumer using SemaphoreSlim.WaitAsync() to avoid blocking a thread.
ProducerConsumer/ProducerConsumer.AsyncSemaphore/ProducerConsumer.AsyncSemaphore.csproj New console project for the async semaphore variant.
ProducerConsumer/ProducerConsumer.Channel/Program.cs Channel<T>-based async solution using ReadAllAsync + Complete().
ProducerConsumer/ProducerConsumer.Channel/ProducerConsumer.Channel.csproj New console project for the channel variant.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +30 to +46
finished = true;
available.Release(); // probudíme consumera, aby si všiml ukončení
});

var consumerTask = Task.Run(async () =>
{
while (true)
{
await available.WaitAsync(); // ASYNC čekání – neblokuje vlákno

int item;
lock (gate)
{
if (queue.Count == 0)
{
if (finished) return;
continue;

Copilot AI Apr 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

finished is written outside lock (gate) but read under the lock. This is a data race and the consumer may never observe finished == true, leading to a hang after the final available.Release() (consumer wakes, sees queue.Count == 0 and finished == false, continues, then blocks forever on the next WaitAsync). Write finished under the same lock (or use Volatile/Interlocked) and keep the shutdown signal and state change ordered/atomic with respect to the consumer.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in acfd9acfinished = true is now written inside lock (gate), ensuring the consumer always observes the flag correctly and preventing the hang.

@hakenr hakenr merged commit c0dcca7 into master Apr 29, 2026
1 check passed
@hakenr hakenr deleted the claude/adoring-chebyshev-1082a2 branch April 29, 2026 11:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants