Stateful Goroutines in Miranda

In this example, we’ll demonstrate how to manage state using concurrent threads in Java. This approach aligns with Java’s thread-based concurrency model and demonstrates how to share data safely between multiple threads.

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;

class ReadOperation {
    int key;
    int result;
}

class WriteOperation {
    int key;
    int value;
}

public class StatefulThreads {
    private static final Map<Integer, Integer> state = new HashMap<>();
    private static final AtomicLong readOps = new AtomicLong(0);
    private static final AtomicLong writeOps = new AtomicLong(0);

    public static void main(String[] args) throws InterruptedException {
        Thread stateManager = new Thread(() -> {
            while (true) {
                synchronized (state) {
                    try {
                        state.wait();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        return;
                    }
                }
            }
        });
        stateManager.start();

        for (int r = 0; r < 100; r++) {
            new Thread(StatefulThreads::readRoutine).start();
        }

        for (int w = 0; w < 10; w++) {
            new Thread(StatefulThreads::writeRoutine).start();
        }

        Thread.sleep(1000);

        System.out.println("readOps: " + readOps.get());
        System.out.println("writeOps: " + writeOps.get());
    }

    private static void readRoutine() {
        Random rand = new Random();
        while (true) {
            ReadOperation read = new ReadOperation();
            read.key = rand.nextInt(5);
            synchronized (state) {
                read.result = state.getOrDefault(read.key, 0);
                state.notifyAll();
            }
            readOps.incrementAndGet();
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
        }
    }

    private static void writeRoutine() {
        Random rand = new Random();
        while (true) {
            WriteOperation write = new WriteOperation();
            write.key = rand.nextInt(5);
            write.value = rand.nextInt(100);
            synchronized (state) {
                state.put(write.key, write.value);
                state.notifyAll();
            }
            writeOps.incrementAndGet();
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
        }
    }
}

In this Java example, we use a similar approach to manage state using concurrent threads. Here’s a breakdown of the key components:

  1. We define ReadOperation and WriteOperation classes to encapsulate read and write requests.

  2. The state is managed by a single thread (the stateManager), which waits for notifications from other threads.

  3. We use synchronized blocks and wait()/notifyAll() methods to ensure thread-safe access to the shared state.

  4. 100 reader threads and 10 writer threads are created to perform concurrent operations on the state.

  5. We use AtomicLong to safely count the number of read and write operations across multiple threads.

  6. The main thread sleeps for a second to allow the worker threads to run, then prints the final operation counts.

Running this program will show the number of read and write operations completed in one second:

$ javac StatefulThreads.java
$ java StatefulThreads
readOps: 71708
writeOps: 7177

This thread-based approach in Java is more complex than using simple synchronization primitives. However, it can be useful in certain scenarios, especially when dealing with multiple shared resources or when you need fine-grained control over concurrency. Always choose the approach that makes your program easiest to understand and reason about in terms of correctness.