Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand Python thread safety

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "how to understand Python thread safety". In daily operation, I believe many people have doubts about how to understand Python thread safety. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubts of "how to understand Python thread safety"! Next, please follow the editor to study!

1. What about thread unsafe?

To understand what thread safety is, you must first understand what thread unsafety is like.

For example, the following code starts two threads and increments the global variable number 100000 times each, one at a time.

From threading import Thread, Lock number = 0 def target (): global number for _ in range (1000000): number + = 1 thread_01 = Thread (target=target) thread_02 = Thread (target=target) thread_01.start () thread_02.start () thread_01.join () thread_02.join () print (number)

Normally our expected output results, one thread increases by 1 million, two threads increase by 2 million, and the output must be 2000000.

But the fact is not what you think, no matter how many times you run, each output will be different, and these outputs have a characteristic is that they are all less than 2 million.

The following is the result of three executions

1459782 1379891 1432921

This phenomenon is that the thread is not safe, the root cause is actually our operation number + = 1, not atomic operation, will lead to thread unsafe.

two。 What is atomic operation?

An atomic operation (atomic operation) is an operation that is not interrupted by a thread scheduling mechanism. Once the operation starts, it runs to the end without switching to another thread.

It is somewhat similar to transactions in a database.

Some common atomic operations are listed in the official documentation of Python

L.append (x) L1.extend (L2) x = L [I] x = L.pop () L1 [iL.pop j] = L2 L.sort () x = y x.field = y D [x] = y D1.update (D2) D.keys ()

And these are not atomic operations.

I = L.append (L [- 1]) L [I] = L [j] D [x] = D [x] + 1

Like above, I use the self-increment operation number + = 1, which is actually equivalent to number = number + 1. You can see that this can be split into multiple steps (read and add first and then assign) and is not an atomic operation.

As a result, when multiple threads read at the same time, it is possible to read the same number value twice, but only add it once, resulting in the number of self-increments less than expected.

When we are still not sure whether our code is atomic, we can try to see it through the dis function in the dis module.

When we execute this code, we can see that the line of number + = 1 is implemented by two bytecodes.

BINARY_ADD: add two values together

STORE_GLOBAL: reassigns the added value

Each bytecode instruction is a whole and cannot be divided, and the effect it achieves is what we call atomic operations.

When a line of code is divided into multiple bytecode instructions, it means that only one bytecode instruction may be executed during thread switching, and if there are variables or resources shared by multiple threads in this line of code, and the split multiple instructions have write operations on the shared variable, data conflicts will occur, resulting in inaccurate data.

For comparison, let's take one of the atomic operations listed above to see if it is true as mentioned on the official website.

Here I will take the update operation of the dictionary as an example. The code and execution process are shown below.

As you can see from the screenshot, info.update (new) is also divided into several operations.

LOAD_GLOBAL: loading global variables

LOAD_ATTR: load properties, get update method

LOAD_FAST: loading new variabl

CALL_FUNCTION: calling function

POP_TOP: perform update operation

But we need to know that what really leads to data conflicts is not the read operation, but the write operation.

With so many bytecode instructions above, there is only one write operation (POP_TOP), so the update method of the dictionary is atomic.

3. Realize artificial atomic operation

In multithreading, we cannot guarantee that all our code is atomic, so how to make our code "atomic" is a very important thing.

The method is also very simple, that is, when you access a resource shared among multiple threads, locking can achieve the effect of an atomic operation. If a code is not executed, it must be executed before it can accept thread scheduling.

Therefore, we use the locking method to make some changes to example 1 to make it "atomic".

From threading import Thread, Lock number = 0 lock = Lock () def target (): global number for _ in range (1000000): with lock: number + = 1 thread_01 = Thread (target=target) thread_02 = Thread (target=target) thread_01.start () thread_02.start () thread_01.join () thread_02.join () print (number)

At this point, no matter how many times you execute, the output is 2000000.

4. Why is Queue thread-safe?

There are three main message communication mechanisms in Python's threading module:

Event

Condition

Queue

Queue is the most commonly used, and we all know that it is thread-safe. When we write and extract it, it will not be interrupted and lead to errors, which is why we do not need additional locks when using queues.

How did he do it?

The root cause is that Queue implements lock primitives, so he can implement artificial atomic operations as he did in Section 3.

Primitive refers to a program composed of several machine instructions to perform a specific function, which is inseparable; that is, the execution of the primitive must be continuous and cannot be interrupted in the process of execution.

At this point, the study on "how to understand Python thread safety" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report