Loading video player…

Python Thread Safety: Using a Lock and Other Techniques (Overview)

Python threading allows you to run parts of your code concurrently, making the code more efficient. However, when you introduce threading to your code without knowing about thread safety, you may run into issues such as race conditions. You solve these with tools like locks, semaphores, events, conditions, and barriers.

By the end of this video course, you’ll be able to identify safety issues and prevent them by using the synchronization primitives in Python’s threading module to make your code thread-safe.

In this video course, you’ll learn:

  • What thread safety is
  • What race conditions are and how to avoid them
  • How to identify thread safety issues in your code
  • What different synchronization primitives exist in the threading module
  • How to use synchronization primitives to make your code thread-safe

Course Prerequisites:

Download

Course Slides (.pdf)

1.4 MB
Download

Sample Code (.zip)

6.6 KB

00:00 Welcome to Thread Safety in Python: Locks and Other Techniques. My name is Christopher, and I will be your guide.

00:07 In this course, you’ll learn about a variety of ways to manage race conditions when coding with the threading library, including two kinds of locks, semaphores, and several ways of doing atomic signaling between threads.

00:21 The code in this course was tested in Python 3.13. Most of the threading stuff has been around for a long time, so any supported version of Python should be sufficient.

00:30 In one very small piece of code, I use the batched() function from itertools, which was introduced in Python 3.12, but it only saves me a couple lines of code, and you could work around that if you want to use something earlier.

00:44 There are several different ways of creating code that supports parallelism and concurrency in Python. One of the lower level primitive libraries is threading, which is a wrapper to your operating system’s thread capabilities. Threads are leaner than multi-process code because they share the same interpreter state, but that leanness through sharing is a bit of a trade-off.

01:05 As most operations in Python aren’t atomic, shared spaces can lead to race conditions where the timing of when two threads fight to make a change affects the final outcome.

01:15 In this case, your code is no longer deterministic, which typically is problematic.

01:21 To deal with race conditions, you need to add atomicity to your code. Thankfully, the threading library has a variety of tools to help you do just that.

01:30 Locks are a way of ensuring only one thread can run a managed block of code at a time. Semaphores are thread-safe counters, and they can be used to limit how many threads use a resource at the same time.

01:42 And events are ways to signal information between threads. There are also two other mechanisms that combine these ideas into higher-level primitives. Conditions are locks that can perform signaling, while barriers are locks that prevent execution of a block until enough threads have arrived at that point.

02:02 This is not an introduction course on threading or concurrency. The next lesson will do a quick review on some threading code and introduce a race condition.

02:10 But if you’ve never done concurrent coding in Python before, this course might not be the best place to start. I’m going to assume you have familiarity with the threading library, have seen ThreadPoolExecutors before, have a grasp of the idea of race conditions, and some glancing familiarity with the GIL.

02:28 Don’t worry. Real Python has content that covers all of this stuff. So if you stumbled across this course first, I can point you where to start instead. The Speed Up Python With Concurrency course covers all those things I just mentioned and more.

02:43 It teaches you the difference between I/O-bound and CPU-bound parallelism, how to use the threading, asyncio and multi-process libraries, and about some of the challenges of concurrent coding like race conditions and the GIL.

02:57 You don’t need deep knowledge of the GIL for this course as long as you understand that it isn’t a solution to most race conditions. But if you are interested in a deeper dive, this course covers Python’s favorite feature to argue about in detail.

03:11 Great, so I haven’t scared you off. Then let’s get started. In the next lesson, I’ll cover a threaded program and introduce a race condition.

Become a Member to join the conversation.