threading.local()
threading. The local () method allows each thread to have its own independent data, which cannot be accessed by other threads.
As shown in the figure:
Or use another more vivid metaphor, which is more appropriate. Compare a process to a company, the threads under the process to the employees of the company, and threading Local () is compared to the company's lockers. Each employee has a separate cabinet, and each employee can only access his own cabinet.
As shown in the figure:
So what does this thing do? For example, when you use Xunlei for multi-threaded download, the download progress of each thread is different, so how to store the download progress is particularly important.
Data storage must be convenient for data retrieval. If the storage structure is well done, the speed of searching and retrieving data will be faster.
threading. In fact, the design idea of local () is also reflected in the context management mechanism of flash framework. The two are basically the same, so now we understand threading After the principle of local (), it will be easy to read the source code of flash framework.
Basic use
Here are the basic usage steps:
- Locker = threading local()
- Use lockers under threads Item name = item. Only this thread can get the item in the future
- When obtaining or using, directly use the lockers The item name is enough. If the item to be obtained is not stored by this thread, an exception will be thrown
Example case:
import threading def jack(article): locker.rose = article print(locker.rose) # Normal removal print(locker.food) # Throw exception def ken(article): locker.food = article print(locker.food) # Normal removal print(locker.rose) # Throw exception if __name__ == "__main__": locker = threading.local() jackTask = threading.Thread(target=jack, args=("rose",)) kenTask = threading.Thread(target=ken, args=("food",)) jackTask.start() kenTask.start() # rose # AttributeError: '_thread._local' object has no attribute 'food' # food # AttributeError: '_thread._local' object has no attribute 'rose'
Principle analysis
We can create a global dictionary to achieve similar functions. The dictionary format is as follows:
locker = { "thread ID" : {"Item name" : "Article itself"}, "thread ID" : {"Item name" : "Article itself"}, "thread ID" : {"Item name" : "Article itself"}, }
As follows:
import threading def task(article): thId = threading.get_ident() # Start storing things locker[thId] = { "rose": article } # Take something out print(locker[thId]["rose"]) if __name__ == "__main__": locker = {} subThreadIns = threading.Thread(target=task, args=("rose",)) subThreadIns.start() # rose
Code optimization
Is it particularly troublesome to access things like this? So we can define a class to make the operation of this locker easier.
As follows:
import threading class Locker: locker = {} def __getattr__(self, name): """When trying to use.This method is triggered when an object property is accessed and cannot be found""" ident = threading.get_ident() return __class__.locker[ident][name] def __setattr__(self, name, value): """When trying to use.This method is triggered when an object property is modified or added""" ident = threading.get_ident() if ident not in __class__.locker: __class__.locker[ident] = {} __class__.locker[ident].update({name: value}) def task(article): # Start storing things locker.rose = article print(locker.rose) if __name__ == "__main__": locker = Locker() subThreadIns = threading.Thread(target=task, args=("rose",)) subThreadIns.start() # rose