Well the Factom approach is the same as many new languages are taking these days - just ban shared memory concurrency entirely and rely on message passing. You can of course implement this style in any language with a small amount of discipline and if you're willing to accept the inefficiency that can come with everything being immutable.
I’ve got two very concurrent codebases on my hands right now and I’ve been experimenting with different approaches. One is a large library that uses classical thread safety techniques like locking of mutable state. It’s a pain to implement indeed, but the big advantage is that the library is thread safe so from the users (i.e. developers) perspective, it’s quite easy to use. There are no thread affinity rules like there would be for a GUI toolkit. You can pretty much use the API in any style or context you like and it will work.
The other is an app that uses the library. Internally it uses an actor-ish sort of model. The “messages” between the frontend actor (GUI thread) and backend actor are actually closures, but otherwise it’s a pretty close approximation to the model. The pure actor model has some pretty tricky problems though.
- If you use real messages you end up writing tons of boilerplate to serialize state into messages and deserialize it again. Using closures and lambdas can help avoid a lot of this boilerplate.
- Inevitably in real apps, some messages are latency sensitive and others are not. Every time I've tried to use the actor model I've encountered this problem. When using old fashioned concurrency programming you can make your locking finer grained quite easily, as long as you watch out for inversions. Then a request that needs a fast response (because it's required for UI rendering) can be served as quickly as possible. With the actor model it's a lot harder to fix this sort of thing because if a big slow request is being processed the small must-be-fast requests jam up behind it.
- With locking you tend to get natural back pressure. With a pure actor design there's no back pressure so if one actor/thread produces work faster than another can consume it you can get OOMs.
So my app has ended up with a mishmash of styles. The core is still actor based. State the UI needs fast access to is replicated across threads using what I call mirrored collections. A mirrored collection is one that observes another (using the JavaFX observable collections) and replicates the deltas across threads. So the backend actor can mutate a bunch of lists and maps (containing immutable objects) and the frontend actor (UI thread) will see the same changes occur on its own copies of those collections at a later time, so those collections can be bound directly onto UI widgets. It's a model that's worked out quite well for me and I think I'll use it again in future.
Given the importance of concurrency I think observable/mirrorable collections would be a neat addition to the Kotlin standard library.
However some things cannot be easily handled this way, like responding to a button press. Technically you could do it web style and have the button disable itself, then send a message to the backend, and wait for the backend to send a response message back to the frontend, but this is hardly worth it when 99% of the time the response can be immediate and fast by simply reaching directly across actors and grabbing the data it needs using a lock.