Threads == Packages?

David Stark / Zarkonnen
15 Oct 2013, 6 a.m.
This is a thought about Java that occurred to me a little while ago. Java threading is pretty scary, because the default model is based around multiple threads accessing the same mutable data and using mutexes to coordinate. This tends to go horribly wrong in all kinds of ways.

A much less scary model is message passing, where all mutable state belongs strictly to a particular thread, and the threads use immutable messages to communicate. The upsides are that it prevents a bunch of failure modes, and indeed makes it fairly easy to de-couple the threads to be in different processes or even machines as needed.

What would be nice when writing code in a message-passing style is some kind of enforcement that a given thread can only access its own state - but this can be tricky if there's quite a lot of code involved.

An unrelated issue with Java is its weird choice of default access level: a variable or method is by default accessible to all members of the same package. This is pretty much never what you want, so everything ends up being prefixed with public or private.

My thought: If you gave each thread exactly one package, you could use the default access level instead of "public". This way, a thread could access and mutate all of its own state but none of some other thread's. Beyond that there would be some specific immutable message data structures.

As an example:

package com.zarkonnen.kitten;

class Kitten {
    void feed() {
        System.out.println("ompft");
    }
}

public class KittenFeeder implements Runnable {
    boolean feedKittenRequest;
    Kitten kitten = new Kitten();
    public synchronized void sendFeedKittenMessage() {
        feedKittenRequest = true;
    }
    public void run() {
        while (true) { // Imagine a more sane bit of code here.
            synchronized(this) {
                if (feedKittenRequest) {
                    kitten.feed();
                    feedKittenRequest = false;
                }
            }
        }
    }
}

package com.zarkonnen.somethingelse;

// Has no access to the Kitten class.
feeder.sendFeedKittenMessage();

It could work, and it might be a nice way of enforcing some order in your multi-threaded application. For example, all the UI code can be in one package, running on the AWT event thread, all the business logic and data in a second, and the networking in a third.

The only fly in the ointment is that package access isn't recursive, so members of package foo.bar don't have access to package foo, forcing you to put everything in the thread into a single package with no sub-packages.