concurrency and threading

Rava2 provides native support for Java's threading model, mapping java.lang.Thread to POSIX pthreads with full monitor synchronization.

thread states

Threads progress through a defined state lifecycle:

statedescription
THREAD_NEWCreated but not yet started
THREAD_RUNNABLEExecuting or ready to execute
THREAD_BLOCKEDWaiting to acquire a monitor lock
THREAD_WAITINGWaiting indefinitely (wait() called)
THREAD_TIMED_WAITINGWaiting with timeout
THREAD_TERMINATEDExecution completed

state transitions

NEW -> start() -> RUNNABLE
RUNNABLE -> synchronized block -> BLOCKED -> acquire lock -> RUNNABLE
RUNNABLE -> wait() -> WAITING -> notify() -> RUNNABLE
RUNNABLE -> sleep() -> TIMED_WAITING -> timeout -> RUNNABLE
RUNNABLE -> run() completes -> TERMINATED

creating threads

with runnable lambda

Thread t = new Thread(() -> {
    System.out.println("Running in thread: " + Thread.currentThread().getName());
});
t.start();
t.join();  // Wait for completion

with runnable implementation

class MyTask implements Runnable {
    public void run() {
        System.out.println("Task executing");
    }
}

Thread t = new Thread(new MyTask());
t.start();

thread api

instance methods

methoddescription
start()Begin thread execution
join()Wait for thread to complete
join(long millis)Wait with timeout
isAlive()Check if thread is still running
getName()Get thread name
setName(String)Set thread name
getPriority()Get thread priority (1-10)
setPriority(int)Set thread priority
interrupt()Request thread interruption
isInterrupted()Check interrupt status

static methods

methoddescription
Thread.currentThread()Get reference to current thread
Thread.sleep(long millis)Pause current thread
Thread.yield()Hint to yield CPU time
Thread.interrupted()Check and clear interrupt status

priority constants

Thread.MIN_PRIORITY   // 1
Thread.NORM_PRIORITY  // 5 (default)
Thread.MAX_PRIORITY   // 10

thread manager

The runtime maintains a global ThreadManager that tracks all threads:

  • Linked list of active threads
  • Global thread manager lock for thread-safe operations
  • Main thread tracking for proper shutdown

monitors and synchronization

Every object in Rava2 can act as a monitor for thread synchronization.

synchronized methods

public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

synchronized blocks

public void transfer(Account from, Account to, int amount) {
    synchronized (from) {
        synchronized (to) {
            from.withdraw(amount);
            to.deposit(amount);
        }
    }
}

monitor internals

Each monitor maintains:

fielddescription
ownerThread holding the lock (or NULL)
entry_countReentrant lock count
wait_queueLinked list of waiting threads
mutexpthread mutex for atomicity
condpthread condition variable

reentrant locking

synchronized void outer() {
    // entry_count = 1
    inner();  // Same thread can re-enter
}

synchronized void inner() {
    // entry_count = 2
    // ... work ...
}  // entry_count = 1

// outer() returns, entry_count = 0, lock released

wait and notify

wait()

synchronized (lock) {
    while (!condition) {
        lock.wait();  // Releases lock, waits for notify
    }
    // Condition is now true, lock is held
}

wait(long timeout)

synchronized (lock) {
    long deadline = System.currentTimeMillis() + timeout;
    while (!condition) {
        long remaining = deadline - System.currentTimeMillis();
        if (remaining <= 0) break;
        lock.wait(remaining);
    }
}

notify() vs notifyAll()

methodbehavior
notify()Wakes one waiting thread (arbitrary selection)
notifyAll()Wakes all waiting threads
synchronized (lock) {
    condition = true;
    lock.notifyAll();  // Wake all waiters
}

wait queue implementation

Threads waiting on a monitor are stored in a WaitNode linked list:

  • FIFO ordering for fairness
  • Nodes track the waiting thread and next pointer
  • notify() removes first node, notifyAll() clears the queue

interruption mechanism

interrupt flag

Each thread has an interrupt flag that can be set by other threads:

Thread worker = new Thread(() -> {
    while (!Thread.currentThread().isInterrupted()) {
        // Do work
    }
    System.out.println("Interrupted, cleaning up");
});

worker.start();
Thread.sleep(1000);
worker.interrupt();  // Sets interrupt flag
worker.join();

interrupt behavior

methodbehavior
interrupt()Sets the interrupt flag
isInterrupted()Checks flag without clearing
Thread.interrupted()Checks and clears the flag

daemon threads

Daemon threads run in the background and don't prevent JVM shutdown:

Thread daemon = new Thread(() -> {
    while (true) {
        // Background task
        Thread.sleep(1000);
    }
});
daemon.setDaemon(true);
daemon.start();
// Main thread exits, daemon is terminated

thread-local exception handling

Each thread maintains its own exception state:

  • exception field stores pending exception
  • Uncaught exceptions propagate to thread termination
  • Exception state cleared on new try block entry

producer-consumer pattern

class BlockingQueue {
    private ArrayList<Object> items = new ArrayList<>();
    private int capacity;

    public BlockingQueue(int capacity) {
        this.capacity = capacity;
    }

    public synchronized void put(Object item) {
        while (items.size() >= capacity) {
            wait();
        }
        items.add(item);
        notifyAll();
    }

    public synchronized Object take() {
        while (items.isEmpty()) {
            wait();
        }
        Object item = items.remove(0);
        notifyAll();
        return item;
    }
}

worker pool example

class WorkerPool {
    private Thread[] workers;
    private BlockingQueue taskQueue;

    public WorkerPool(int numWorkers) {
        taskQueue = new BlockingQueue(100);
        workers = new Thread[numWorkers];

        for (int i = 0; i < numWorkers; i++) {
            workers[i] = new Thread(() -> {
                while (true) {
                    Runnable task = (Runnable) taskQueue.take();
                    task.run();
                }
            });
            workers[i].start();
        }
    }

    public void submit(Runnable task) {
        taskQueue.put(task);
    }
}

parallel computation example

public class ParallelSum {
    public static void main(String[] args) {
        int[] data = new int[1000000];
        for (int i = 0; i < data.length; i++) {
            data[i] = i;
        }

        int numThreads = 4;
        long[] partialSums = new long[numThreads];
        Thread[] threads = new Thread[numThreads];
        int chunkSize = data.length / numThreads;

        for (int t = 0; t < numThreads; t++) {
            int threadIndex = t;
            int start = t * chunkSize;
            int end = (t == numThreads - 1) ? data.length : start + chunkSize;

            threads[t] = new Thread(() -> {
                long sum = 0;
                for (int i = start; i < end; i++) {
                    sum += data[i];
                }
                partialSums[threadIndex] = sum;
            });
            threads[t].start();
        }

        for (Thread t : threads) {
            t.join();
        }

        long total = 0;
        for (long sum : partialSums) {
            total += sum;
        }
        System.out.println("Total: " + total);
    }
}

vm mutex and thread safety

Rava2 uses a global VM mutex to ensure thread safety:

  • All object allocations acquire the VM lock
  • Garbage collection runs under the lock (stop-the-world)
  • Native methods can release the lock for blocking operations

pthread integration

Thread implementation maps directly to pthreads:

Java operationpthread call
Thread.start()pthread_create()
Thread.join()pthread_join()
Thread.sleep()nanosleep()
Thread.yield()sched_yield()
synchronizedpthread_mutex_lock/unlock()
wait()pthread_cond_wait()
notify()pthread_cond_signal()
notifyAll()pthread_cond_broadcast()

thread memory management

  • Each thread has its own call stack
  • Thread stacks are scanned as GC roots
  • Thread name memory tracked with name_allocated flag
  • pthread TLS (thread-local storage) handled by suppression file

debugging threads

./rava2 -d program.java   # Debug output shows thread operations
make valgrind             # Detect race conditions (with --tool=helgrind)

The valgrind.supp file suppresses known false positives from pthread's internal memory management.