This video discusses the actor model of parallelism and how it can help us to make parallel programs that don't suffer from things like race conditions.
lovely, simple explanation, thanks~! do you have some real world examples where this model is used please - I'm finding it difficult to understand its applicability?
The best way to see what has been done with this is probably the case studies at LightBend (www.lightbend.com/case-studies?_ga=2.1132534.69086303.1632434455-1874277060.1632434454). The later videos in that playlist go through some small examples.
Messages will be processed sequentially in a single actor. However, multiple actors can be processing at the same time. So if you have a system with a large number of actors, you can have significant parallelism. You do have to be careful that you don't make one actor become a bottleneck for the processing.
Each actor has their own thread. Imagine you pass a message with an Array in it. Arrays are mutable. Also assume that the actor that passed the message with the Array still has a reference to that array. Let's call that Array arr, though it might have different variable names in each actor. This means that the first actor could do arr(0) = someValue and the second actor could do the same thing. They are doing it in the same Array, so the value of the Array in the end depends on which one went first. That, by definition, is a race condition. Since you generally don't have control over which actor will be scheduled to process messages at and given time, that means you now have code that produces results that are non-deterministic for your code.
@@MarkLewis Thank you for the explanation! So, the Actor Model itself does _not_ guarantee that there is no race condition(I think that's called "thread safe"), so we ourselves(developers) should be careful not to make mutable messages between the actors? And if the messages between the actors are _not_ mutable, do the results are deterministic?
@@starriet not 100%, but it comes really close. There are just a few basic rules to follow. The main one is to make messages immutable. The other is not doing things outside the actor model that introduce race conditions. I find those rules are pretty easy to follow, especially in Scala, where data tends to be immutable by default.
@@MarkLewis Thanks. Does "really close" mean that if the messages are not mutable, the results are almost (but not 100%) deterministic? Does it become 100% deterministic if we follow the two rules you mentioned? Thank you!
@@starriet whether it is deterministic or not depends on how you set things up. Simple example with four actors. Let's call them Start, P1, P2, and Combine. As the name implies, we start with Start, and it sends messages to P1 and P2. They do some processing, and when they are done, they send their results to Combine. The order in which the messages arrive at Combine is not deterministic. So whether the whole thing is deterministic depends on how the results are combined. If Combine does a "take first" or "take last" type of thing, we have a non-deterministic race condition. However, if it adds the results after it gets both of them, it will be deterministic. The actor model prevents data races and multiple threads modifying the same piece of memory. So it will prevent inconsistent state. One of the projects I have had students do in the past is a multiplayer text game. I have them use Actors to allow multiple threads while keeping state threadsafe. The players themselves and the rooms are Actors. If two players try to get a single item at the same time, we have something of a race condition. The outcome is valid though, as long as exactly one of the players gets the item. A data race could create a situation where neither player gets it or both players get it. The Actor model prevents that, but it isn't completely deterministic.
Manual locking is error prone. Do it too much and you are killing the benefits of parallelism and risking deadlock. Do it too little and you have race conditions. Using actors it is easy to model the parts of your program that are safe to run in parallel as separate elements and the framework will give you safety and high levels of parallelism.
Actors in less than 5 minutes. We need more brief explanations like this about fancy sounding functional concepts.
I'm glad that you found it to be useful.
Simple and informative, just what I needed.
Best explanation of actor model on UA-cam. Trust me, I have watched a bunch of videos :)
Thanks! I'm glad that you found it useful.
Great video and diagrams! Who knew that explaining the actor model could be so simple
Thank you very much. I'm glad that you found it useful.
The instructor is awesome! Perfect explanation .
Thanks!
lovely, simple explanation, thanks~! do you have some real world examples where this model is used please - I'm finding it difficult to understand its applicability?
The best way to see what has been done with this is probably the case studies at LightBend (www.lightbend.com/case-studies?_ga=2.1132534.69086303.1632434455-1874277060.1632434454). The later videos in that playlist go through some small examples.
@@MarkLewis ah, thank you :)
crystal clear explanation Mark. Thank you.
Glad you found it helpful.
Will it not makei it sequential? please help me understand
Messages will be processed sequentially in a single actor. However, multiple actors can be processing at the same time. So if you have a system with a large number of actors, you can have significant parallelism. You do have to be careful that you don't make one actor become a bottleneck for the processing.
Can you tell how messages being mutable cause any issues ?
Each actor has their own thread. Imagine you pass a message with an Array in it. Arrays are mutable. Also assume that the actor that passed the message with the Array still has a reference to that array. Let's call that Array arr, though it might have different variable names in each actor. This means that the first actor could do arr(0) = someValue and the second actor could do the same thing. They are doing it in the same Array, so the value of the Array in the end depends on which one went first. That, by definition, is a race condition. Since you generally don't have control over which actor will be scheduled to process messages at and given time, that means you now have code that produces results that are non-deterministic for your code.
@@MarkLewis Thank you for the explanation! So, the Actor Model itself does _not_ guarantee that there is no race condition(I think that's called "thread safe"), so we ourselves(developers) should be careful not to make mutable messages between the actors?
And if the messages between the actors are _not_ mutable, do the results are deterministic?
@@starriet not 100%, but it comes really close. There are just a few basic rules to follow. The main one is to make messages immutable. The other is not doing things outside the actor model that introduce race conditions. I find those rules are pretty easy to follow, especially in Scala, where data tends to be immutable by default.
@@MarkLewis Thanks. Does "really close" mean that if the messages are not mutable, the results are almost (but not 100%) deterministic? Does it become 100% deterministic if we follow the two rules you mentioned? Thank you!
@@starriet whether it is deterministic or not depends on how you set things up. Simple example with four actors. Let's call them Start, P1, P2, and Combine. As the name implies, we start with Start, and it sends messages to P1 and P2. They do some processing, and when they are done, they send their results to Combine. The order in which the messages arrive at Combine is not deterministic. So whether the whole thing is deterministic depends on how the results are combined. If Combine does a "take first" or "take last" type of thing, we have a non-deterministic race condition. However, if it adds the results after it gets both of them, it will be deterministic. The actor model prevents data races and multiple threads modifying the same piece of memory. So it will prevent inconsistent state.
One of the projects I have had students do in the past is a multiplayer text game. I have them use Actors to allow multiple threads while keeping state threadsafe. The players themselves and the rooms are Actors. If two players try to get a single item at the same time, we have something of a race condition. The outcome is valid though, as long as exactly one of the players gets the item. A data race could create a situation where neither player gets it or both players get it. The Actor model prevents that, but it isn't completely deterministic.
Why not just use lock?
Manual locking is error prone. Do it too much and you are killing the benefits of parallelism and risking deadlock. Do it too little and you have race conditions. Using actors it is easy to model the parts of your program that are safe to run in parallel as separate elements and the framework will give you safety and high levels of parallelism.