Python thread details

Source: Internet
Author: User
This article mainly introduces the details of Python threads. This article describes all aspects of threads, such as basic thread knowledge, thread status, thread synchronization (lock), and thread communication (condition variable, for more information, see 1. thread basics

1.1. thread status

The thread has five states. The State conversion process is shown in:

1.2. Thread synchronization (lock)

The advantage of multithreading is that it can run multiple tasks at the same time (at least it feels like this ). However, when the thread needs to share data, the data may not be synchronized. Consider this situation: all elements in a list are 0, the thread "set" changes all elements from the back to 1, and the thread "print" reads and prints the list from the back to the back. Then, when the thread "set" starts to change, the thread "print" will print the list, and the output will be half 0 and half 1, which means the data is not synchronized. To avoid this situation, the lock concept is introduced.

There are two locks: locked and unlocked. Every time a thread such as "set" wants to access shared data, it must first get a lock. if another thread such as "print" has been locked, it will suspend the thread "set, that is, synchronous blocking. wait until the thread "print" is accessed, release the lock, and then let the thread "set" continue. After such processing, when the list is printed, either all 0 is output or all 1 is output, and no embarrassing scenes of half 0 and half 1 are displayed.

Shows the interaction between threads and locks:

1.3. thread communication (condition variable)

However, there is another embarrassing situation: The list does not exist at the beginning, but is created through the thread "create. If "set" or "print" is accessed when "create" is not running, an exception occurs. The lock can solve this problem, but "set" and "print" will require an infinite loop-they do not know when "create" will run, making "create" notify "set" and "print" after running is obviously a better solution. Therefore, conditional variables are introduced.

Conditional variables allow threads such as "set" and "print" to wait when the conditions are not met (when the list is None) and send a notification when the conditions are met (the list has been created, tell "set" and "print" that the conditions already exist. you should get up and work. then "set" and "print" will continue to run.

Shows the interaction between a thread and a condition variable:

1.4. State conversion of thread running and blocking
Finally, let's look at the conversion of thread running and blocking states.

There are three blocking situations:

Synchronization blocking refers to a state in which a thread requests a lock and enters this state at regular intervals. once the lock is obtained successfully, the thread returns to the running state;
Waiting for blocking refers to the status of waiting for notifications from other threads. after the thread obtains the condition lock, the "waiting" call will enter this status. once other threads send a notification, the thread will enter the synchronous blocking status, again, the competition conditions are locked;
Other blocking means the blocking of calling time. sleep (), anotherthread. join () or waiting for IO. in this state, the thread will not release the obtained lock.

Tips: If you can understand the content, the following theme will be very easy; and the content is the same in most popular programming languages. (This means you can't understand it.> _ <if the author's level is low, you should also understand the tutorials for others)

2. thread

Python supports threads through two standard libraries: thread and threading. Thread provides a low-level, original thread, and a simple lock.

The code is as follows:


# Encoding: UTF-8
Import thread
Import time

# A function used for execution in a thread
Def func ():
For I in range (5 ):
Print 'func'
Time. sleep (1)

# End the current thread
# This method is equivalent to thread. exit_thread ().
Thread. exit () # When func returns, the thread will also end

# Start a thread and the thread starts running immediately
# This method is equivalent to thread. start_new_thread ().
# The first parameter is the method, and the second parameter is the method parameter.
Thread. start_new (func, () # When there is no parameter in the method, a blank tuple is required.

# Create a lock (LockType, cannot be directly instantiated)
# This method is equivalent to thread. allocate_lock ().
Lock = thread. allocate ()

# Determine whether the lock is locked or released
Print lock. locked ()

# A lock is usually used to control access to shared resources.
Count = 0

# Obtain the lock. if the lock is successfully obtained, True is returned.
# When the optional timeout parameter is not set, it will be blocked until it is locked.
# Otherwise, False will be returned after the timeout
If lock. acquire ():
Count + = 1

# Release a lock
Lock. release ()

# All threads provided by the thread module end simultaneously after the main thread ends.
Time. sleep (6)

Other methods provided by the thread module:

Thread. interrupt_main (): terminate the main thread in other threads.
Thread. get_ident (): obtains a magic number that represents the current thread. it is often used to obtain thread-related data from a dictionary. This number has no meaning, and will be reused by the new thread after the thread ends.

Thread also provides a ThreadLocal class for managing thread-related data, named thread. _ local, which is referenced in threading.

Because thread does not provide many thread functions, it cannot continue running after the main thread ends, and does not provide conditional variables. Generally, the thread module is not used.

3. threading

Threading is a Java-based thread model design. Lock and Condition variables are the basic behavior of objects in Java (each object has a Lock and Condition variable), while in Python, they are independent objects. Python Thread provides a subset of Java Thread behaviors. without a priority or Thread Group, the Thread cannot be stopped, paused, recovered, or interrupted. Some static methods implemented by Python in Java Thread are provided in threading in the form of module methods.

Common methods provided by the threading module:

Threading. currentThread (): returns the current thread variable.
Threading. enumerate (): returns a list containing running threads. Running means that the threads before and after startup and termination are not included.
Threading. activeCount (): returns the number of running threads, with the same results as len (threading. enumerate.

Classes provided by the threading module:

Thread, Lock, Rlock, Condition, [Bounded] Semaphore, Event, Timer, local.

3.1. Thread

Thread is a Thread class. similar to Java, there are two ways to use it: directly pass in the method to be run or inherit from Thread and overwrite run ():

The code is as follows:


# Encoding: UTF-8
Import threading

# Method 1: the method to be executed is used as the constructor to pass the parameter to the Thread.
Def func ():
Print 'func () passed to thread'

T = threading. Thread (target = func)
T. start ()

# Method 2: inherit from Thread and override run ()
Class MyThread (threading. Thread ):
Def run (self ):
Print 'mythread extended from thread'

T = MyThread ()
T. start ()

Constructor:

Thread (group = None, target = None, name = None, args = (), kwargs = {})
Group: Thread group, which has not been implemented yet. the database reference prompts that it must be None;
Target: method to be executed;
Name: specifies the thread name;
Args/kwargs: parameter of the method to be passed in.

Instance method:

IsAlive (): returns whether the thread is running. Running means starting and before termination.
Get/setName (name): get/set the thread name.
Is/setDaemon (bool): Gets/sets whether to guard the thread. The initial value is inherited from the thread that created the thread. When no non-daemon thread is still running, the program will be terminated.
Start (): start the thread.
Join ([timeout]): blocks the thread in the current context until the thread that calls this method terminates or reaches the specified timeout (optional parameter ).

An example of using join:

The code is as follows:


# Encoding: UTF-8
Import threading
Import time

Def context (tJoin ):
Print 'in threadContext .'
TJoin. start ()

# TContext will be blocked until threadJoin is terminated.
TJoin. join ()

# TJoin continues after termination.
Print 'out threadContext .'

Def join ():
Print 'in threadJoin .'
Time. sleep (1)
Print 'out threadJoin .'

TJoin = threading. Thread (target = join)
TContext = threading. Thread (target = context, args = (tJoin ,))

TContext. start ()

Running result:

The code is as follows:


In threadContext.
In threadJoin.
Out threadJoin.
Out threadContext.

3.2. Lock

The Lock is the lowest available synchronous command. When the Lock is locked, it is not owned by a specific thread. Lock includes two states: locked and unlocked, and two basic methods.

It can be considered that the Lock has a Lock pool. when the thread requests the Lock, it moves the thread into the pool until it gets the Lock and leaves the pool. The threads in the pool are in the synchronization blocking status in the status chart.

Constructor:

Lock ()

Instance method:

Acquire ([timeout]): Enables the thread to enter the synchronization blocking state and tries to get the lock.
Release (): release the lock. The thread must be locked before use; otherwise, an exception will be thrown.

The code is as follows:


# Encoding: UTF-8
Import threading
Import time

Data = 0
Lock = threading. Lock ()

Def func ():
Global data
Print '% s acquire lock...' % threading. currentThread (). getName ()

# When acquire ([timeout]) is called, the thread will always be blocked,
# Wait until the lock is obtained or until the timeout seconds are reached (the timeout parameter is optional ).
# Return whether to obtain the lock.
If lock. acquire ():
Print '% s get the lock.' % threading. currentThread (). getName ()
Data + = 1
Time. sleep (2)
Print '% s release lock...' % threading. currentThread (). getName ()

# Call release () to release the lock.
Lock. release ()

T1 = threading. Thread (target = func)
T2 = threading. Thread (target = func)
T3 = threading. Thread (target = func)
T1.start ()
T2.start ()
T3.start ()

3.3. RLock

RLock (reentrant lock) is a synchronous command that can be requested multiple times by the same thread. RLock uses the concepts of "owned threads" and "recursive level". when it is locked, RLock is owned by a thread. Threads with RLock can call acquire () again. The release () must be called for the same number of times when the lock is released.

It can be considered that RLock contains a lock pool and a counter whose initial value is 0. each time acquire ()/release () is successfully called, the counter will be + 1/-1, when the value is 0, the lock is not locked.

Constructor:

RLock ()

Instance method:
Acquire ([timeout])/release (): Similar to Lock.

The code is as follows:


# Encoding: UTF-8
Import threading
Import time

Rlock = threading. RLock ()

Def func ():
# First request lock
Print '% s acquire lock...' % threading. currentThread (). getName ()
If rlock. acquire ():
Print '% s get the lock.' % threading. currentThread (). getName ()
Time. sleep (2)

# Second request lock
Print '% s acquire lock again...' % threading. currentThread (). getName ()
If rlock. acquire ():
Print '% s get the lock.' % threading. currentThread (). getName ()
Time. sleep (2)

# First release lock
Print '% s release lock...' % threading. currentThread (). getName ()
Rlock. release ()
Time. sleep (2)

# Second release lock
Print '% s release lock...' % threading. currentThread (). getName ()
Rlock. release ()

T1 = threading. Thread (target = func)
T2 = threading. Thread (target = func)
T3 = threading. Thread (target = func)
T1.start ()
T2.start ()
T3.start ()

3.4. Condition

Condition (Condition variable) is usually associated with a lock. When you need to share a Lock among multiple Contidion instances, you can pass a Lock/RLock instance to the constructor. Otherwise, it will generate an RLock instance.

It can be considered that in addition to the Lock pool contained in the Lock, the Condition also contains a waiting pool. the threads in the pool are in the waiting and blocking status in the status chart until another thread calls Y ()/notifyAll () notification. the thread enters the lock pool and waits for the lock.

Constructor:

Condition ([lock/rlock])

Instance method:

Acquire ([timeout])/release (): Call the corresponding method of the associated lock.
Wait ([timeout]): calling this method will enable the thread to enter the Condition wait pool for notification and release the lock. The thread must be locked before use; otherwise, an exception will be thrown.
Y (): Call this method to select a thread from the wait pool and notify the thread that receives the notification to automatically call acquire () to try to get the lock (enter the lock pool ); other threads are still waiting in the pool. The lock will not be released when this method is called. The thread must be locked before use; otherwise, an exception will be thrown.
Yyall (): calling this method will notify all threads in the wait pool that will enter the lock pool to try to get the lock. The lock will not be released when this method is called. The thread must be locked before use; otherwise, an exception will be thrown.

The example is a common producer/consumer model:

The code is as follows:


# Encoding: UTF-8
Import threading
Import time

# Product
Product = None
# Condition variables
Con = threading. Condition ()

# Producer method
Def produce ():
Global product

If con. acquire ():
While True:
If product is None:
Print 'produce ...'
Product = 'Anything'

# Notify the consumer that the product has been produced
Con. sort Y ()

# Waiting for notification
Con. wait ()
Time. sleep (2)

# Consumer method
Def consume ():
Global product

If con. acquire ():
While True:
If product is not None:
Print 'sume ...'
Product = None

# Notify the producer that the product is no longer available
Con. sort Y ()

# Waiting for notification
Con. wait ()
Time. sleep (2)

T1 = threading. Thread (target = produce)
T2 = threading. Thread (target = consume)
T2.start ()
T1.start ()

3.5. Semaphore/BoundedSemaphore

Semaphore is one of the oldest synchronous commands in the history of computer science. Semaphore manages a built-in counter. each time acquire () is called-1, release () is called + 1. The counter cannot be smaller than 0. when the counter is 0, acquire () will block the thread to the synchronization lock status until other threads call release ().

Based on this feature, Semaphore is often used to synchronize objects with "visitor ceiling", such as connection pools.

The only difference between BoundedSemaphore and Semaphore is that the former checks whether the counter value has exceeded the counter initial value when calling release (). if it exceeded, an exception is thrown.

Constructor:
Semaphore (value = 1): value is the initial value of the counter.

Instance method:
Acquire ([timeout]): requests Semaphore. If the counter is 0, the blocking thread is in synchronization blocking state; otherwise, the counter-1 is returned immediately.
Release (): release Semaphore. the counter is + 1. if BoundedSemaphore is used, the release count is checked. The release () method does not check whether the thread has obtained Semaphore.

The code is as follows:


# Encoding: UTF-8
Import threading
Import time

# Counter initial value is 2
Semaphore = threading. Semaphore (2)

Def func ():

# Request Semaphore. after the request is successful, the counter is-1; when the counter is 0, it is blocked.
Print '% s acquire semaphore...' % threading. currentThread (). getName ()
If semaphore. acquire ():

Print '% s get semaphore' % threading. currentThread (). getName ()
Time. sleep (4)

# Release Semaphore, counter + 1
Print '% s release semaphore' % threading. currentThread (). getName ()
Semaphore. release ()

T1 = threading. Thread (target = func)
T2 = threading. Thread (target = func)
T3 = threading. Thread (target = func)
T4 = threading. Thread (target = func)
T1.start ()
T2.start ()
T3.start ()
T4.start ()

Time. sleep (2)

# The main thread that does not obtain semaphore can also call release.
# If BoundedSemaphore and t4 are used to release semaphore, an exception is thrown.
Print 'mainthread release semaphore without acquire'
Semaphore. release ()

3.6. Event

Event is one of the simplest thread communication mechanisms: one thread notifies the Event, and the other threads wait for the Event. Event has a built-in flag with the initial value of False. it is set to True when set () is called and False when clear () is called. Wait () will block the thread to wait for blocking.

Event is actually a simplified Condition. The Event does not have a lock and cannot cause the thread to enter the synchronization blocking status.

Constructor:

Event ()

Instance method:
IsSet (): Returns True if the built-in flag is True.
Set (): sets the flag to True and notifies all threads waiting for blocking to resume running.
Clear (): set the flag to False.
Wait ([timeout]): returns immediately if the flag is True. Otherwise, the blocked thread waits for other threads to call set ().

The code is as follows:


# Encoding: UTF-8
Import threading
Import time

Event = threading. Event ()

Def func ():
# Wait for the event to enter the waiting for blocking status
Print '% s wait for event...' % threading. currentThread (). getName ()
Event. wait ()

# Enter the running status after receiving the event
Print '% s recv event.' % threading. currentThread (). getName ()

T1 = threading. Thread (target = func)
T2 = threading. Thread (target = func)
T1.start ()
T2.start ()

Time. sleep (2)

# Send event notifications
Print 'mainthread set event .'
Event. set ()

3.7. Timer
Timer (Timer) is a derived class of Thread, used to call a method after a specified time.

Constructor:
Timer (interval, function, args = [], kwargs = {})
Interval: the specified time.
Function: method to be executed
Args/kwargs: method parameters

Instance method:
Timer is derived from Thread and no instance method is added.

The code is as follows:


# Encoding: UTF-8
Import threading

Def func ():
Print 'Hello timer! '

Timer = threading. Timer (5, func)
Timer. start ()

3.8. local

Local is a class that starts with a lowercase letter and is used to manage data of thread-local. For the same local, the thread cannot access the attributes set by other threads. the attributes set by the thread are not replaced by the attributes set by other threads with the same name.

We can regard local as a "thread-attribute Dictionary" dictionary, local encapsulates the use of the thread as the key to retrieve the corresponding attribute dictionary, and then use the attribute name as the key to retrieve the details of the attribute value.

The code is as follows:


# Encoding: UTF-8
Import threading

Local = threading. local ()
Local. tname = 'main'

Def func ():
Local. tname = 'notmain'
Print local. tname

T1 = threading. Thread (target = func)
T1.start ()
T1.join ()

Print local. tname

Familiar with Thread, Lock, and Condition can deal with the vast majority of scenarios where Thread needs to be used. in some cases, local is also very useful. These classes are used at the end of this article to demonstrate the scenarios mentioned in the thread basics:

The code is as follows:


# Encoding: UTF-8
Import threading

Alist = None
Condition = threading. Condition ()

Def doSet ():
If condition. acquire ():
While alist is None:
Condition. wait ()
For I in range (len (alist) [:-1]:
Alist [I] = 1
Condition. release ()

Def doPrint ():
If condition. acquire ():
While alist is None:
Condition. wait ()
For I in alist:
Print I,
Print
Condition. release ()

Def doCreate ():
Global alist
If condition. acquire ():
If alist is None:
Alist = [0 for I in range (10)]
Condition. policyall ()
Condition. release ()

Tset = threading. Thread (target = doSet, name = 'tset ')
Tprint = threading. Thread (target = doPrint, name = 'tprint ')
Tcreate = threading. Thread (target = doCreate, name = 'tcreate ')
Tset. start ()
Tprint. start ()
Tcreate. start ()

Full text

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.