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

Case Analysis of Python Thread Safety

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

Share

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

This article mainly introduces the relevant knowledge of "Python thread safety case analysis". The editor shows you the operation process through the actual case. The operation method is simple, fast and practical. I hope this article "Python thread safety case analysis" can help you solve the problem.

1. What is thread safety?

Thread safety, the name is very direct, in the case of multithreading is safe, multithreaded operation is safe.

For example, a function that calculates addition, whether it is 1000 or 10,000 threads, we hope that the result of its execution is always correct. 1 / 1 must always be equal to 2, rather than 1 / 1 becomes 3 or 4 when there are fewer threads.

Usually we use thread safety to decorate a class and a function:

We'll say that the class I designed is thread-safe.

This means that in a multithreaded environment, functions that call this class at the same time will not have exceptions that are not expected by the function settings (in the case of 1-1-3 above)

What classes are thread-safe in Python?

Dict and list,tuple are all thread-safe.

They are guaranteed by the global interpreter, and this lock: GIL (global interpreter lock) ensures that only one thread can perform the corresponding operation at any one time. Referenc

But this remark is also unclear.

Now let's analyze it with the transfer:

Xuewei_account = dict () xuewei_account ['amount'] = 10. If amount is negative, the transferred amount is def transfer (money): xuewei_account [' amount'] + = money

As above, the code is a function to transfer the amount to the jb_account (account).

The dict type is used here, and GIL ensures that only one thread operates the account.

Here is the code for multiple threads to operate:

Import randomimport threadingimport datetimeimport timexuewei_account = dict () xuewei_account ['amount'] = 10' amount is a negative number, that is, the transferred amount def transfer (money): xuewei_account ['amount'] + = money# create four tasks to transfer to the account of the repeated study committee threads = [] for i in range (200): T1 = threading.Thread (target=lambda: transfer (- 1) threads.append (T1) T2 = threading.Thread (target=lambda: transfer (1)) Threads.append (T2) for t in threads: t.start () # No sleep this time Using join to wait for all threads to finish executing # the join function must be called after the thread start, or there will be an error. For t in threads: t.join () print ("-" * 16) print ("active threads:", threading.active_count ()) print ("active threads:", threading.current_thread () .name) print ("account balance of the academic committee:", xuewei_account)

The output result of this code running is normal, because it is repeated + 1 Universe Mui 1, and in the end it must be to restore the original account balance.

Although there are multiple threads, each thread only reads and writes xuewei_account once, so dict is safe at this time.

But after we change the assignment to modify the dict operation more (especially in a thread repeatedly get the value and then modify it), like the following code:

Import randomimport threadingimport datetimeimport timexuewei_account = dict () xuewei_account ['amount'] = 10' amount is a negative number, that is, the transfer amount def transfer (money): for i in range (100000): xuewei_account ['amount'] = xuewei_account [' amount'] + money# create 400tasks to repeat transfer to the account of the academic Committee threads = [] for i in range (200): T1 = threading.Thread (target=lambda: transfer (- 1)) threads. Append (T1) T2 = threading.Thread (target=lambda: transfer (1)) threads.append (T2) for t in threads: t.start () for t in threads: t.join () print ("-" * 16) print ("active threads:" Threading.active_count () print ("active thread:", threading.current_thread (). Name) print ("account balance of the academic committee:", xuewei_account)

This is the result of one run (the value of acount is not guaranteed to be the same each time):

We can see that dict still can't handle multiple threads writing repeatedly.

The difference here is that each thread only reads and writes a large number of xuewei_account, although dict is safe, but the account is modified between multiple threads, and the program method stack operates to the old value (see figure below).

It is mainly the following code:

Xuewei_account ['amount'] + = money # is xuewei_account [' amount'] = xuewei_account ['amount'] + money

Another step of abstraction and simplification can be written as follows:

A = a + b

Each thread performs a + b operation, and the final value of a should be await 2b.

The above operation means that the following happens:

In a thread, there may be a thread T1 that gets a value, ready to add b.

Another thread, T2, has completed the aroomb operation, changing the value of a to aroomb.

But then T1 takes the value of an and then performs the aposib operation, changing the value of a to aqb.

In this way, a b is missing, and the final result is that axi2b becomes astatb (because T1 takes the old value of a, and T1 continues to execute after the middle T2 is finished)

Of course, the actual interaction between multithreads is more random than the image above.

Third, how to achieve true thread safety?

It is thread-safe for dict to read data, but it is easy to cause data confusion when it is read and written repeatedly.

If we are to design a thread-safe function, it must not involve any shared variables or functions that have no state dependency at all

Def thread_safe_method (): pass1. Stateless function

For example, in the following addition function, no matter how many threads call, the return value is always the expected aaccounb.

Def add (a, b): return a + b2. The other reduces complexity to simplicity.

Maybe we can convert multithreading to single threading, which requires a thread-safe medium.

This is the end of the introduction to "Python thread safety instance analysis". Thank you for reading. If you want to know more about the industry, you can follow the industry information channel. The editor will update different knowledge points for you every day.

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