How does Actors work compared to threads?

Solution 1:

The actor model operates on message passing. Individual processes (actors) are allowed to send messages asynchronously to each other. What distinguishes this from what we normally think of as the threading model, is that there is (in theory at least) no shared state. And if one believes (justifiably, I think) that shared state is the root of all evil, then the actor model becomes very attractive.

We shouldn't get over excited, however. The actor model does not (contrary to some allegations) make it impossible to have deadlocks. The actor model also does not prevent you from having contention for resources between different processes -- message queues, for instance. The model is only "lock-free" above a certain level. At a lower level, for coordinating message queues, locking is still required.

Can't a thread be seen as an actor and send messages to other threads?

Well, yes and no. No, if you're just using the approach of putting mutexes around shared memory locations. Then the threads share this state -- they both have access to this memory, can both read it, re-write it, etc. But you can build an actor model on top of a threading model, and indeed all actor implementation do have threads underneath. I've hacked together something like this (very badly) by giving each thread a queue guarded by a mutex -- just for fun. To get an idea of how actor-thread impedance is managed, see my question from a year ago.

Can I use the Actor Model in any language by using threads differently?

Yes, but it'll take a bit more work. Your favourite language may well have a message-passing library, so that would be the first thing to investigate. Also, you should investigate the use of immutable data structures. Notice that if a data structure is immutable, then you've essentially dealt with the "shared-state" problem -- multiple threads can hold references to immutable data without anything bad happening. There's a reason why actor languages tend to also be functional languages (erlang, scala).

You may also want to have a look at Software Transactional Memory, which is a different but also compelling model. Clojure is my favourite example of that.

Solution 2:

I wouldn't say that actors always pass messages asynchronously--that would be too slow. Case in point, the JActor project uses 2-way messages (request/response) to better model a method call. And most requests are serviced synchronously.

JActor (a Java library) also does not use locks. Only some atomic and concurrent data structures, with a few semaphores thrown in. Message passing is about .8 Billion messages per second.

https://github.com/laforge49/JActor