Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

>Maybe it's just me, but message flows and behavior is a lot easier to think about than concurrent access to shared state.

In general, I agree with you. I think the actor model makes concurrent code readable, understandable, and potentially easier to maintain due to that readability. People inexperienced with concurrency might find it a lot more approachable than the alternatives; an actor feels so similar to an object at times and are easier to use than threads or green-threads. I've personally found that actors also give me performance right out of the box, when I could have really screwed something up with locking.

But other than that, doesn't it all boil down to the same thing?

Actors serialize access/modification of state through ordered messages. Locks serialize access/modification of state through acquiring the lock. And when you have complex access or modification patterns in your code, the actor model doesn't help all that much. To me it's like each message acquires the lock to the actor state.

Sure, you can see what messages cause what behavior or state change for an actor A, but the rest of the system can still be complex. Which actors send a given message to actor A, and why or when do they do this? It's not obvious, and the same complexity can be found in event-driven systems, lock-y threaded systems, etc.

>With the re-entrant Swift actors proposed in the link, I'm not so sure it will be easy.

I'm personally not convinced about re-entrant actors. I don't see why you'd give up the guarantee of blocking until a message is fully handled.

They state:

"Moreover, it helps ensure that actors can make timely progress within a concurrent system, and that a particular actor does not end up unnecessarily blocked on a long-running asynchronous operation (say, downloading a file)."

This example is particularly weak in my opinion. An actor could block on the long-running async operation, of course. But isn't that the brute-force/naive approach? I can't see any one doing this in practice.

You could create a long-running actor whose only job is to sequentially handle requests to download files and send the file descriptors back as a message response. You could create a worker pool to do that as well. You could decompose your one actor into a staged pipeline of actors, so any requests that block can go to one pipeline, and other swiftly handled messages can go to another pipeline. Of course, none of these are simple solutions, but neither is designing an actor with re-entrancy in mind.

>that makes it hard to think about again

I agree. However, they do seem to be pushing the envelope and not just reinventing the wheel. I'm curious to see how this plays out.



> But other than that, doesn't it all boil down to the same thing?

> Actors serialize access/modification of state through ordered messages. Locks serialize access/modification of state through acquiring the lock. And when you have complex access or modification patterns in your code, the actor model doesn't help all that much. To me it's like each message acquires the lock to the actor state.

I think yes and no. The big thing for me is it's easy to mess up locks. I've locked one thing and modified another, or read outside the lock, then locked to write, and the value changed. I also just did something similar except there's a mix of locks and atomics (kernel side of pthread umutexes needs to use atomics to mark the mutex as contested).

Actors serialization of work via mailbox (and its implicit locking) makes it hard to make basic mistakes. Of course, complex flows are still complex.

We're definitely in agreement on re-entrant actors. On the plus side, if it doesn't work well, I expect they'll change course.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: