Reader small image

You're reading from  Advanced Python Programming - Second Edition

Product typeBook
Published inMar 2022
PublisherPackt
ISBN-139781801814010
Edition2nd Edition
Right arrow
Author (1)
Quan Nguyen
Quan Nguyen
author image
Quan Nguyen

Quan Nguyen is a Python programmer and machine learning enthusiast. He is interested in solving decision-making problems under uncertainty. Quan has authored several books on Python programming and scientific computing. He is currently pursuing a Ph.D. degree in computer science at Washington University in St. Louis, researching Bayesian methods in machine learning.
Read more about Quan Nguyen

Right arrow

Chapter 14: Race Conditions

In this chapter, we will discuss the concept of race conditions and their potential causes in the context of concurrency. The definition of a critical section, which is a concept highly relevant to race conditions and concurrent programming, will also be covered. We will use some example code in Python to simulate race conditions and the solutions that are commonly used to address them. Finally, real-life applications that commonly deal with race conditions will also be discussed.

In this chapter, we will cover the following topics:

  • The concept of race conditions
  • Simulating race conditions in Python
  • Locks as a solution to race conditions
  • Race conditions in real life

This chapter, similar to the previous two chapters, offers a closer look at what could go wrong in concurrent programming and exposes us to a wide range of approaches in terms of how to avoid and prevent that. In this chapter, our focus will be on race conditions...

Technical requirements

The code for this chapter can be found in the following GitHub repository: https://github.com/PacktPublishing/Advanced-Python-Programming-Second-Edition/tree/main/Chapter14.

The concept of race conditions

Typically, a race condition is defined as a phenomenon during which the output of a system is both indeterminate and dependent on the scheduling algorithm and the order in which tasks are scheduled and executed. When data becomes mishandled or corrupted during this process, a race condition becomes a bug in the system. Given the nature of this problem, it is quite common for a race condition to occur in concurrent systems, which emphasizes the importance of scheduling and coordinating independent tasks.

A race condition can occur in both an electronic hardware system and a software application; in this chapter, we will only discuss race conditions in the context of software development – specifically, concurrent software applications. This section will cover the theoretical foundations of race conditions and their root causes along with the concept of critical sections.

Critical sections

Critical sections indicate shared resources that...

Simulating race conditions in Python

If you have already downloaded the code for this book from the GitHub page, go ahead and navigate to the Chapter14 folder.

To simulate a race condition, first, we need a common resource. In this case, it's a counter variable along with multiple threads that can access it simultaneously. Let's take a look at the Chapter14/example1.py file—specifically, the update() function, as follows:

import random
import time
def update():
    global counter
    current_counter = counter # reading in shared resource
    time.sleep(random.randint(0, 1)) # simulating heavy 
    calculations
    counter = current_counter + 1 # updating shared 
    resource

The goal of the preceding update() function is to increment a global variable called counter, and it is to be called by a separate thread in our script. Inside the function...

Locks as a solution to race conditions

Intuitively, since the race conditions that we observed arose when multiple threads or processes accessed and wrote to a shared resource simultaneously, the key idea behind solving race conditions is isolating the executions of different threads/processes, especially when interacting with a shared resource. Specifically, we need to make sure that a thread/process can only access the shared resource after any other threads/processes interacting with the resource have finished their interactions with that resource.

With locks, we can turn a shared resource inside a concurrent program into a critical section, whose integrity of data is guaranteed to be protected. We will see this in action next.

The effectiveness of locks

A critical section guarantees the mutual exclusion of a shared resource and cannot be accessed concurrently by multiple processes or threads; this will prevent any protected data from being updated or altered with conflicting...

Race conditions in real life

In particular, we will discuss the topics of security, file management, and networking. Race conditions don't simply exist in simple, minimal code examples about global counters. They are present in many important tasks such as security, file management, and networking. In this section, we will briefly discuss what some of these examples might look like from a theoretical perspective.

Security

Concurrent programming can have significant implications in terms of the security of the system in question. Recall that a race condition arises between the process of reading and altering the data of a resource; a race condition in an authenticating system can cause the corruption of data between the time of check (when the credentials of an agent are checked) and the time of use (when the agent can utilize the resource). This problem is also known as a Time-Of-Check-To-Time-Of-Use (TOCTTOU) bug, which is undoubtedly detrimental to security systems.

...

Summary

A race condition occurs when two or more threads/processes access and alter a shared resource simultaneously, resulting in mishandled and corrupted data. Race conditions also have significant implications in real-life applications, such as security, operating systems, and networking.

In this chapter, we learned how to isolate the execution of different threads/processes to tackle many forms of race conditions. We have examined how to use locks to turn a shared resource into a critical section to protect the integrity of its data. Additionally, we have discussed a number of practical disadvantages when it comes to using locks.

In the next chapter, we will consider one of the biggest problems in Python concurrent programming: the infamous Global Interpreter Lock (GIL). You will learn about the basic idea behind the GIL, its purposes, and how to effectively work with it in concurrent Python applications.

Questions

  1. What is a critical section?
  2. What is a race condition, and why is it undesirable in a concurrent program?
  3. What is the underlying cause of a race condition?
  4. How can locks solve the problem of race conditions?
  5. Why are locks sometimes undesirable in a concurrent program?
  6. What is the significance of race conditions in real-life systems and applications?

Further reading

For more information, please refer to the following resources:

  • Parallel Programming with Python, by Jan Palach, Packt Publishing Ltd, 2014.
  • Python Parallel Programming Cookbook, by Giancarlo Zaccone, Packt Publishing Ltd, 2015.
  • Race Conditions and Critical Sections (tutorials.jenkov.com/java-concurrency/race-conditions-and-critical-sections), by Jakob Jenkov.
  • Race conditions, files, and security flaws; or the tortoise and the hare redux, by Matt Bishop, Technical Report CSE-95-98 (1995).
  • Computer and Information Security, Chapter 11, Software Flaws and Malware 1 Illustration (slideplayer.com/slide/10319860/).
lock icon
The rest of the chapter is locked
You have been reading a chapter from
Advanced Python Programming - Second Edition
Published in: Mar 2022Publisher: PacktISBN-13: 9781801814010
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Quan Nguyen

Quan Nguyen is a Python programmer and machine learning enthusiast. He is interested in solving decision-making problems under uncertainty. Quan has authored several books on Python programming and scientific computing. He is currently pursuing a Ph.D. degree in computer science at Washington University in St. Louis, researching Bayesian methods in machine learning.
Read more about Quan Nguyen