Async Techniques and Examples in Python Transcripts
Chapter: Course conclusion and review
Lecture: Review: Thread safety
0:00 Once you start working on threads, you need
0:02 to be really careful about thread safety.
0:05 One rule of thumb is share as little data
0:07 between threads as possible.
0:08 That's not always possible or even useful.
0:11 At the heart of this thread safety problem is
0:14 even normal functions, normal serial functions
0:18 they have to take our program and evolve it
0:20 from one state to another, and that often
0:22 means changing different parts of our program
0:24 putting those all into some new state.
0:26 In going through that process, there's no way
0:28 to avoid entering temporarily invalid states.
0:32 So we have a function call, it's going to do
0:34 a little work, it's going to change the state
0:36 of one of our objects, do a little more work
0:38 change the state of another one of our objects
0:40 and it's done, going to make some final changes
0:42 that make the entire system consistent again.
0:45 So we start the function call, it goes through
0:47 those transformations and then when we get
0:49 to the end, everything is good.
0:51 So what's the problem?
0:52 Remember, the problem is in serial code
0:55 well, there is no problem.
0:56 But in concurrent code with threads, we could
0:59 come along here, this thread could get suspended
1:02 the other thread could come along and look
1:04 at that red object and the blue object
1:05 at the bottom and say, "Oh, this must be what
1:08 "the values are," and go and run with it.
1:10 Doesn't matter that it's put back.
1:11 It's already used that to make a decision
1:13 and it's off to the races to make a bad decision
1:16 do something wrong.
1:17 So we must make sure when our apps go through
1:19 this temporarily invalid state, other threads
1:22 cannot come and see it.
1:23 We have to put up a little privacy wall.
1:25 And so that's what thread safety is primarily about.
1:28 So if we're going to do this, probably the best
1:30 way to work with is what's called a reentrant lock.
1:32 So import threading, create a lock based on an RLock.
1:35 Remember a regular lock is not reentrant.
1:37 That can be problematic, potentially.
1:40 So we're using RLock and then we just say
1:42 with that lock and then we do those potentially
1:45 unsafe operations, and by unsafe I mean we're
1:48 entering into this temporarily invalid state.
1:50 And we don't want other things to see it
1:51 so this with block, that's like our privacy
1:53 wall for the data that we're manipulating.
1:55 Once we get it all back in the right shape
1:57 we can release the lock and other parts
1:59 of our app can go and work with it.
2:02 So this is all great.
2:03 Remember the other thing we spoke about was
2:04 if you're taking multiple locks at the same time
2:07 if you take them in different orders you're going to
2:09 end up in a deadlock, so you have to have
2:11 some mechanism to take locks in the same order
2:13 all the time if you're taking multiple locks.