

{"id":12071,"date":"2018-03-28T12:02:09","date_gmt":"2018-03-28T06:32:09","guid":{"rendered":"https:\/\/data-flair.training\/blogs\/?p=12071"},"modified":"2026-04-24T16:44:58","modified_gmt":"2026-04-24T11:14:58","slug":"python-multithreading","status":"publish","type":"post","link":"https:\/\/data-flair.training\/blogs\/python-multithreading\/","title":{"rendered":"Python Multithreading &#8211; Threads, Locks, Functions of Multithreading"},"content":{"rendered":"<p>In this lesson, we\u2019ll learn to implement Python Multithreading with an example. We will use the module \u2018threading\u2019 for this.<\/p>\n<p>We will also have a look at the Functions of Python Multithreading, Thread &#8211; Local Data, Thread Objects in Python multithreading, and <span id=\"13_Using_locks_conditions_and_semaphores_in_the_with-statement\">using locks, conditions, and semaphores in the with-statement in Python Multithreading.<br \/>\n<\/span><\/p>\n<p>So, let&#8217;s start the Multithreading in Python Tutorial.<\/p>\n<div id=\"attachment_12076\" style=\"width: 1210px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Multithreading-in-Python-01.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-12076\" class=\"wp-image-12076 size-full\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Multithreading-in-Python-01.jpg\" alt=\"Python Multithreading\" width=\"1200\" height=\"628\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Multithreading-in-Python-01.jpg 1200w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Multithreading-in-Python-01-150x79.jpg 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Multithreading-in-Python-01-300x157.jpg 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Multithreading-in-Python-01-768x402.jpg 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Multithreading-in-Python-01-1024x536.jpg 1024w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><p id=\"caption-attachment-12076\" class=\"wp-caption-text\">Python Multithreading &#8211; Functions, Threads, and Locks in Multithreading<\/p><\/div>\n<h3>What is Python Multithreading?<\/h3>\n<p>Let&#8217;s understand first what a thread is in Python.<\/p>\n<ul>\n<li>A thread is the smallest unit of execution in a process.<\/li>\n<li>It is said to be a lightweight process as it has multiple threads that can run in a process.<\/li>\n<li>Threads share the same memory, code, and variables.<\/li>\n<\/ul>\n<h3>Functions in Python Multithreading<\/h3>\n<p>We have the following functions in the Python Multithreading module:<\/p>\n<div id=\"attachment_36530\" style=\"width: 1210px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Functions-in-Python-Multithreading-01.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-36530\" class=\"size-full wp-image-36530\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Functions-in-Python-Multithreading-01.jpg\" alt=\"Python Multithreading - Threads, Locks, Functions of Multithreading\" width=\"1200\" height=\"630\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Functions-in-Python-Multithreading-01.jpg 1200w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Functions-in-Python-Multithreading-01-150x79.jpg 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Functions-in-Python-Multithreading-01-300x158.jpg 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Functions-in-Python-Multithreading-01-768x403.jpg 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Functions-in-Python-Multithreading-01-1024x538.jpg 1024w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Functions-in-Python-Multithreading-01-520x273.jpg 520w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><p id=\"caption-attachment-36530\" class=\"wp-caption-text\">Python Multithreading Tutorial &#8211; Functions of Multithreading in Python<\/p><\/div>\n<h4>1. active_count() in Python Multithreading<\/h4>\n<p>This returns the number of alive(currently) Thread objects. This is equal to the length of the list that enumerate() returns.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; threading.active_count()<\/pre>\n<p><strong>Output<\/strong><\/p>\n<div class=\"code-output\">2<\/div>\n<h4>2. current_thread() in Python Multithreading<\/h4>\n<p>Based on the caller\u2019s thread of control, this returns the current Thread object.<\/p>\n<p>If this thread of control isn\u2019t through \u2018threading\u2019, it returns a dummy thread object with limited functionality.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; threading.current_thread()<\/pre>\n<p><strong>Output<\/strong><\/p>\n<div class=\"code-output\">&lt;_MainThread(MainThread, started 14352)&gt;<\/div>\n<h4>3. get_ident() in Python Multithreading<\/h4>\n<p>get_ident() returns the current thread\u2019s identifier, which is a non-zero integer. We can use this to index a dictionary of thread-specific data.<\/p>\n<p>Apart from that, it has no special meaning. When one thread exits, and another creates, Python recycles such an identifier.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; threading.get_ident()<\/pre>\n<p><strong>Output<\/strong><\/p>\n<div class=\"code-output\">14352<\/div>\n<h4>4. enumerate() in Python Multithreading<\/h4>\n<p>This returns a list of all alive(currently) Thread objects. This includes the main thread, daemonic threads, and dummy thread objects created by current_thread().<\/p>\n<p>This obviously doesn\u2019t include terminated threads as well as those that haven\u2019t begun yet.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; threading.enumerate()<\/pre>\n<p><strong>Output<\/strong><\/p>\n<div class=\"code-output\">\n<p>[&lt;_MainThread(MainThread, started 14352)&gt;, &lt;Thread(SockThread, started daemon 9864)&gt;<\/p>\n<\/div>\n<h4>5. main_thread() in Python Multithreading<\/h4>\n<p>This method returns the main Thread object. Normally, it is that thread that started the interpreter.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; threading.main_thread()<\/pre>\n<p><strong>Output<\/strong><\/p>\n<div class=\"code-output\">\n<p>&lt;_MainThread(MainThread, started 14352)&gt;<\/p>\n<\/div>\n<h4>6. settrace(func) in Python Multithreading<\/h4>\n<p>settrace() traces a function for all threads we started using \u2018threading\u2019. The argument func passes to sys.settrace() for each thread before it calls its run() method.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; def sayhi():\r\n     print(\"Hi\")\r\n&gt;&gt;&gt; threading.settrace(sayhi)\r\n&gt;&gt;&gt;<\/pre>\n<h4>7. setprofile(func) in Python Multithreading<\/h4>\n<p>This method sets a profile function for all threads we started from \u2018threading\u2019. It passes <i>func<\/i> to sys.setprofile() for each thread before it calls its run() method.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; threading.setprofile(sayhi)\r\n&gt;&gt;&gt;<\/pre>\n<h4>8. stack_size([size]) in Python Multithreading<\/h4>\n<p>stack_size() returns the stack size of a thread when creating new threads. \u00a0<i>size <\/i>is the stack size we want to use for subsequently created threads.<\/p>\n<p>This must be equal to 0 or a positive integer of value at least 32,768 (32KiB). When not specified, it uses 0.<\/p>\n<p>And if it doesn\u2019t support changing thread stack size, it raises a RuntimeError.<\/p>\n<p>When we pass an invalid stack size, it raises a ValueError and does not modify it.<\/p>\n<p>The minimum stack size it currently supports to guarantee enough stack space for the interpreter itself is 32KiB.<\/p>\n<p>Some platforms may need a minimum stack size of greater than 32KiB. Others may need to allocate in multiples of the system memory page size.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; threading.stack_size()<\/pre>\n<p>Apart from functions, \u2018threading\u2019 also defines a constant.<\/p>\n<h4>9. TIMEOUT_MAX in Python Multithreading<\/h4>\n<p>This holds the maximum allowed value for this constant, the timeout parameter for blocking functions like Lock.acquire(), Condition.wait(), RLock.acquire(), and others.<\/p>\n<p>If we denote a timeout greater than this, it raises an OverflowError.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; threading.TIMEOUT_MAX<\/pre>\n<p><strong>Output<\/strong><\/p>\n<div class=\"code-output\">\n<p>4294967.0<\/p>\n<\/div>\n<p>In Java, locks and condition variables are the basic behavior of every object. Whereas in Python, they are individual objects.<\/p>\n<p>Here, the class Thread supports some of the functionality of class Thread in Java.<\/p>\n<p>However, currently, we have no thread groups, priorities, and we cannot destroy, stop, suspend, resume, or interrupt threads.<\/p>\n<p>When we implement the static methods from Java\u2019s Thread, they map to module-level functions. This way, \u2018threading\u2019 is much like Java\u2019s threading model in design.<\/p>\n<p>Next in the Python Multithreading tutorial is Thread &#8211; Local Data and Thread Objects.<\/p>\n<h3>Python Thread-Local Data<\/h3>\n<p>That data for which the values are thread-specific is thread-local. To manage such data, we can create an instance of local\/a subclass and then store attributes on it.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; mydata=threading.local()\r\n&gt;&gt;&gt; mydata.x=7\r\n&gt;&gt;&gt;<\/pre>\n<p>These instance values differ for each thread. We have the following class denoting thread-local data:<\/p>\n<p>class threading.local<\/p>\n<p>Next in the Python Multithreading Tutorial is Thread Objects.<\/p>\n<h3>Python Thread Objects<\/h3>\n<p>The Thread class that we mentioned earlier in this blog denotes an activity running in a separate thread of control.<\/p>\n<p>We can represent this activity either by passing a callable object to the constructor, ot by overriding the method run() in a subclass.<\/p>\n<p>You must make sure not to override other methods in a subclass, except for the constructor. In short, only override a class\u2019 __init__() and run() methods.<\/p>\n<p>Once the interpreter creates a thread object, we must start its activity by calling its start() method. This will invoke its run() method in a separate thread of control.<\/p>\n<p>Once this happens, we consider the thread to be \u2018alive\u2019. When run() terminates normally or raising an exception we did not handle, it is no longer alive.<\/p>\n<p>To test whether a thread is alive, we may use the method is_alive().<\/p>\n<p>A thread may call another\u2019s join() method. This will block the calling thread until the other terminates.<\/p>\n<p>Threads have names, and we can pass these names to the constructor, and even read or modify them.<\/p>\n<p>We can flag a thread as a \u2018daemon thread\u2019. This means that the whole program exits when only the daemon threads remain.<\/p>\n<p>This initial value comes from the creating thread. We can set this flag via the property \u2018daemon\u2019, or via the constructor argument \u2018daemon\u2019.<\/p>\n<p>Daemons abruptly stop at shutdown, and they may not properly release all the resources held. These resources may include open files, database transactions, and others.<\/p>\n<p>To stop our threads gracefully, we must make them non-daemonic. It is also preferable to use a suitable signaling process, like an Event.<\/p>\n<p>The \u2018main thread\u2019 object pertains to the initial thread of control in our program; it isn\u2019t a daemon.<\/p>\n<p>Finally, it is possible that the interpreter creates \u2018dummy thread objects\u2019. These are \u2018alien threads\u2019 (threads of control started outside \u2018threading\u2019, for ex, directly from C code).<\/p>\n<p>Such objects have limited functionality and are always live and daemonic. We cannot join() them. We can also never delete them since it is impossible to detect when they terminate.<\/p>\n<p>This is the class:<\/p>\n<p>class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)<\/p>\n<p>Take note:<\/p>\n<ul>\n<li>Always call the constructor with keyword arguments. It has the following arguments:<\/li>\n<li><i>group<\/i> must be None. Python reserves this for future extension when we implement a ThreadGroup class.<\/li>\n<li><i>target<\/i> is a callable object that run() will invoke. The default for this is None, which means it calls nothing.<\/li>\n<li><i>name<\/i> is the name of the thread. The default for this is \u201cThread-N\u201d. Here, N is a small decimal number.<\/li>\n<li><i>args<\/i> is an argument tuple. It helps invoke the target. The default for this is ().<\/li>\n<li><i>Kwargs<\/i> is a dictionary holding keyword arguments. Even this helps invoke the target. The default for this is {}.<\/li>\n<li><i>daemon<\/i> decides whether the thread is daemonic. When None, it inherits the daemonic property from the current thread. The default for this is None.<\/li>\n<li>Ensure that you invoke the base class constructor(Thread.__init__()) first if the subclass overrides the constructor.<\/li>\n<\/ul>\n<p>The thread has the following methods:<\/p>\n<div id=\"attachment_36533\" style=\"width: 1210px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Thread-Objects-01.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-36533\" class=\"size-full wp-image-36533\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Thread-Objects-01.jpg\" alt=\"Python Multithreading - Threads, Locks, Functions of Multithreading\" width=\"1200\" height=\"630\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Thread-Objects-01.jpg 1200w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Thread-Objects-01-150x79.jpg 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Thread-Objects-01-300x158.jpg 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Thread-Objects-01-768x403.jpg 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Thread-Objects-01-1024x538.jpg 1024w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Thread-Objects-01-520x273.jpg 520w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><p id=\"caption-attachment-36533\" class=\"wp-caption-text\">Python Multithreading Tutorial &#8211; Python Thread Object<\/p><\/div>\n<h4>1. start() in python thread<\/h4>\n<p>This starts thread activity. For a thread object, we can call it maximum once; if we call it again, it raises a RuntimeError.<\/p>\n<p>This lets run() for the object invoke in a separate thread of control.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; threading.Thread.start(threading.current_thread())<\/pre>\n<p><strong>Output<\/strong><\/p>\n<div class=\"code-output\">\n<p>Traceback (most recent call last):File &#8220;&lt;pyshell#135&gt;&#8221;, line 1, in &lt;module&gt;<\/p>\n<p>threading.Thread.start(threading.current_thread())<\/p>\n<p>RuntimeError: threads can only be started once<\/p>\n<\/div>\n<h4>2. run() in python thread<\/h4>\n<p>This method explains the thread\u2019s activity. It invokes the callable object we passed to the object\u2019s constructor as the target argument, if it exists.<\/p>\n<p>This is with keyword and sequential arguments from <i>kwargs<\/i> and <i>args<\/i>.<\/p>\n<p>We can override run() in a subclass.<\/p>\n<h4>3. join(timeout=None) in python thread<\/h4>\n<p>For join() to work, we must wait until the thread terminates.<\/p>\n<p>Because when that happens, it blocks the calling thread until the one on which we call join() terminates normally or via an exception we did not handle, or until a <i>timeout<\/i> occurs.<\/p>\n<p>When you do provide a <i>timeout<\/i> (other than None), make sure it is a floating-point number. This is so you can pass a timeout in seconds or fractions.<\/p>\n<p>So, what is the return value? Well, join() always returns None. Hence, you\u2019ll need to call is_alive() after calling join() to determine if a timeout happened.<\/p>\n<p>If we find out that it is indeed still alive, then we infer that the join() call timed out.<\/p>\n<p>However, if <i>timeout<\/i> is None, or if we did not pass it, this blocks the operation until the thread terminates. We can join() a thread many times.<\/p>\n<p>Finally, join() will raise a RuntimeError if we try to join the current thread, because that causes a deadlock.<\/p>\n<p>To join() a thread before we start it also causes an error.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; threading.Thread.join(threading.current_thread())<\/pre>\n<p><strong>Output<\/strong><\/p>\n<div class=\"code-output\">\n<p>Traceback (most recent call last):File &#8220;&lt;pyshell#138&gt;&#8221;, line 1, in &lt;module&gt;<\/p>\n<p>threading.Thread.join(threading.current_thread())<\/p>\n<p>RuntimeError: cannot join current thread<\/p>\n<\/div>\n<h4>4. name in Python thread<\/h4>\n<p>This is a string we use for identification; it has no meaning. We can also give the same meaning to multiple threads. The constructor sets the initial name.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; threading.Thread.name='First'\r\n&gt;&gt;&gt;<\/pre>\n<h4>5. getName() and setName() in python thread<\/h4>\n<p>These are old getter and setter APIs for the <i>name<\/i>. We use them directly as properties.<\/p>\n<h4>6. ident in Python thread<\/h4>\n<p>If we started the thread, this returns its identifier. Otherwise, it returns None. Note that it is a non-zero integer, like in the get_ident() function.<\/p>\n<p>Python may recycle identifiers when one thread exits, and another creates. Such identifiers exist even after a thread exits.<\/p>\n<h4>7. is_alive() in python thread<\/h4>\n<p>This returns whether the thread is alive. is_alive() returns true from just before run() starts until just after it terminates.<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; threading.Thread.is_alive(threading.current_thread())<\/pre>\n<p><strong>Output<\/strong><\/p>\n<div class=\"code-output\">\n<p>True<\/p>\n<\/div>\n<h4>8. daemon in Python thread<\/h4>\n<p>daemon is a Boolean value that tells us whether the thread is a daemon. If it is, it returns True. We must set it before we call start().<\/p>\n<p>Otherwise, it raises a RuntimeError. Its initial value comes from the creating thread. The main thread is not a daemon; hence, all threads in the main thread have a default of False for <i>daemon<\/i>.<\/p>\n<p>When only daemon threads remain, the whole program exits.<\/p>\n<h4>9. isDaemon() and setDaemon() in python thread<\/h4>\n<p>These are old getter and setter APIs for the <i>daemon<\/i>. You can use them directly as properties. With this lets move to our next topic in Python Multithreading tutorial.<\/p>\n<h3>Python Lock Objects<\/h3>\n<p>A synchronization primitive, a primitive lock, does not belong to a certain thread when locked.<\/p>\n<p>This is the lowest-level synchronization primitive we currently have in Python, and we implement it using the extension module _thread.<\/p>\n<p>Such a lock can be in one of two states: \u2018locked\u2019 and \u2018unlocked\u2019. When we create a lock, it is in the \u2018unlocked\u2019 state. It also has two methods- acquire() and release().<\/p>\n<p>When we want to lock it, acquire() changes its state to \u2018locked\u2019, and immediately returns it. If it were \u2018locked\u2019 instead, then acquire() blocks until another thread calls release().<\/p>\n<p>This changes the state to \u2018unlocked\u2019. Finally, acquire() resets it to \u2018locked\u2019, and then returns immediately.<\/p>\n<p>If you try to release a lock that is already unlocked, it raises a RuntimeError.<\/p>\n<p>These locks also support the CMP(Context Management Protocol).<\/p>\n<p>When acquire() blocks more than one thread, only one thread continues when release() resets the state to \u2018unlocked\u2019. Which one, you ask? Well, we can\u2019t say.<\/p>\n<p>Also, all methods execute atomically.<\/p>\n<p>This is the class:<\/p>\n<p>class threading.Lock<\/p>\n<p>This call implements primitive lock objects. Once a thread acquires a lock, the interpreter blocks further attempts to acquire it.<\/p>\n<p>Only after it releases does any other thread have a chance in acquiring it. Any thread may release a lock.<\/p>\n<h4>1. acquire(blocking=True, timeout=-1) in Python Lock Object<\/h4>\n<p>This method acquires a blocking or non-blocking lock. When <i>blocking<\/i>=True, it blocks until the lock unlocks. Then, it changes its state to \u2018locked\u2019, and returns True.<\/p>\n<p>And when it is False, it does not block. A call with <i>blocking<\/i>=True that blocks, immediately returns False. Otherwise, it sets the lock to \u2018locked\u2019 and returns True.<br \/>\n<i><\/i><\/p>\n<p><i>timeout<\/i> is a floating-point argument. When it has a positive value, it blocks for a maximum of the <i>timeout<\/i> number of seconds, as long as the lock isn\u2019t acquirable.<\/p>\n<p>When it is -1, it denotes an unbounded wait.<\/p>\n<p>When <i>blocking<\/i> is False, we cannot specify a <i>timeout<\/i>.<\/p>\n<p>Also, if the lock acquires successfully, it returns True; otherwise, False, like when the <i>timeout<\/i> expires.<\/p>\n<h4>2. release() in Python Lock Object<\/h4>\n<p>This method releases a lock. You can call it from any thread. This means that any thread can release a lock, no matter which thread has acquired it.<\/p>\n<p>When \u2018locked\u2019, release() resets it to \u2018unlocked\u2019, and returns. If other threads wait for it to unlock, only one gets to continue once it unlocks.<\/p>\n<p>When we call release() on an \u2018unlocked\u2019 lock, it raises a RuntimeError.<\/p>\n<p>release() doesn\u2019t return any value.<\/p>\n<p>Any doubt yet in Python Multithreading Tutorial? Please Comment.<\/p>\n<h3>Python RLock Objects<\/h3>\n<p>RLock is a very important topic when you learn Python Multithreading. An RLock is a reentrant lock. It is a synchronization primitive that a certain thread can acquire again and again.<\/p>\n<p>It does so using concepts like \u2018owning thread\u2019 and \u2018recursion level\u2019, and locked\/unlocked states. When locked, an RLock belongs to a certain thread, but when unlocked, no thread owns it.<\/p>\n<p>Now, how does this work? To lock, a thread calls acquire(). Now that this thread owns the lock, it returns. To unlock it, a thread calls release().<\/p>\n<p>It is also possible to nest acquire()\/release() pairs. The outermost release() resets the lock to the \u2018unlocked\u2019 state. It also lets another blocked thread continue.<\/p>\n<p>Reentrant locks also support CMP(Context Management Protocol).<\/p>\n<p>This is the class:<\/p>\n<p>class threading.RLock<\/p>\n<p>RLock implements reentrant lock objects. Such a lock is released only by the thread holding it. A thread can acquire it again without blocking.<\/p>\n<p>However, it must release it each time it acquires it.<\/p>\n<p>It has two methods:<\/p>\n<h4>1. acquire(blocking=True, timeout=-1) in Python RLock Object<\/h4>\n<p>acquire() lets us acquire a blocking or non-blocking lock. Without arguments, if the thread already owns the lock, this method ups the recursion level by one and then returns.<\/p>\n<p>If it doesn\u2019t already own it, and another thread owns it, it blocks until the lock \u2018unlocks\u2019.<\/p>\n<p>And once unlocked, and if it does not belong to any other thread, acquire() declares ownership and sets the recursion level to 1, and then returns.<\/p>\n<p>If more than one thread waits blocked at once, only one will get ownership.<\/p>\n<p>This method returns no value. Finally, when we set <i>blocking<\/i> to True, it does the same things we discussed, and then returns True.<\/p>\n<p>When <i>blocking<\/i> is False, however, it does not block. When a call without arguments blocks, it returns False.<\/p>\n<p>Otherwise, it does what it does for a call without arguments, and then returns True.<\/p>\n<p>And when we call acquire() with a <i>timeout<\/i>, which is a floating-point number, with a positive value, this blocks for a maximum of the <i>timeout<\/i> number of seconds, as long as we cannot acquire the lock.<\/p>\n<p>If a thread has acquired it, it returns True; \u00a0if a <i>timeout<\/i> has elapsed, it returns False.<\/p>\n<h4>2. release() in Python RLock Object<\/h4>\n<p>This method releases a lock and decrements the recursion level. Once the decrement is 0, it resets the lock to the \u2018unlocked\u2019 state.<\/p>\n<p>This means no thread owns it. If other threads are blocked, only one of them may continue. If the decrement is non-zero, the lock stays in the \u2018locked\u2019 state and belongs to the calling thread.<\/p>\n<p>You should only call release() when the calling thread actually owns the lock. If it is already \u2018unlocked\u2019, this raises a RuntimeError.<\/p>\n<p>release() returns no value.<\/p>\n<p>Now lets come to Condition Objects in Python Multithreading.<\/p>\n<h3>Python Condition Objects<\/h3>\n<p>A condition variable always pertains to a lock, and we can pass it in, or it is created by default. When several such condition variables must share a lock, we can pass it in.<\/p>\n<p>But we don\u2019t need to exclusively track a lock; it is a part of the condition object.<\/p>\n<p>A condition variable follows CMP (Context Management Protocol) in that it uses the with-statement to acquire the associated lock as long as the enclosed block is alive. acquire() and release() call the lock\u2019s methods.<\/p>\n<p>For other methods, we must call them with the associated lock that the thread holds. Once wait() releases the lock, it blocks until another thread wakes it up with a call to notify() or notify_all().<\/p>\n<p>After this, wait() acquires the lock again, and then returns. We can also specify a <i>timeout<\/i>.<\/p>\n<p>While notify() awakens one waiting thread, if any, notify_all() awakens all threads waiting for the condition variable.<\/p>\n<p>Note that these two methods do not release the lock. So, the threads awakened do not return from wait() immediately.<\/p>\n<p>They return only when the calling thread for notify() or notify_all() gives up ownership of the lock.<\/p>\n<p>This is the class:<\/p>\n<p>class threading.Condition(lock=None)<\/p>\n<p>Condition implements condition variable objects. A condition variable lets any number of threads wait until another thread notifies them.<\/p>\n<p>If <i>lock<\/i> is None, and we do pass it, make sure it\u2019s a Lock or RLock object. This should also serve as the underlying lock; this creates a new RLock object.<\/p>\n<p>It has the following methods:<\/p>\n<div id=\"attachment_36535\" style=\"width: 1090px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Condition-Objects-01.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-36535\" class=\"size-full wp-image-36535\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Condition-Objects-01.jpg\" alt=\"Python Multithreading - Threads, Locks, Functions of Multithreading\" width=\"1080\" height=\"1080\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Condition-Objects-01.jpg 1080w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Condition-Objects-01-150x150.jpg 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Condition-Objects-01-300x300.jpg 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Condition-Objects-01-768x768.jpg 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Condition-Objects-01-1024x1024.jpg 1024w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Condition-Objects-01-160x160.jpg 160w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Condition-Objects-01-320x320.jpg 320w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Python-Condition-Objects-01-520x520.jpg 520w\" sizes=\"auto, (max-width: 1080px) 100vw, 1080px\" \/><\/a><p id=\"caption-attachment-36535\" class=\"wp-caption-text\">Python Multithreading Tutorial &#8211; Python Condition Object<\/p><\/div>\n<h4>1. acquire(*args) in Python Condition Object<\/h4>\n<p>This acquires the underlying lock. It calls the corresponding method on it and returns what that method returns.<\/p>\n<h4>2. release() in Python Condition Object<\/h4>\n<p>This releases the underlying lock. It calls the corresponding method on it and returns nothing.<\/p>\n<h4>3. wait(timeout=None) in Python Condition Object<\/h4>\n<p>This method waits until a timeout happens or until someone notifies it. If at the time of calling wait(), the calling thread doesn\u2019t own the lock, this raises a RuntimeError.<\/p>\n<p>wait() releases the underlying lock, then blocks until a notify()\/notify_all() call for the same condition variable in another thread wakes it up, or until a <i>timeout<\/i> happens.<\/p>\n<p>And once this happens, it acquires the lock again and then returns.<\/p>\n<p>When we do pass a <i>timeout<\/i>, and that isn\u2019t None, make sure it\u2019s a floating-point number denoting a timeout for the operation in seconds or fractions.<\/p>\n<p>If the underlying lock is an RLock, its release() method doesn\u2019t release it, because this doesn\u2019t necessarily unlock it if it was acquired multiple times recursively.<\/p>\n<p>So, what do we do? We use an internal interface of the RLock class. This unlocks it even when it was recursively acquired many times.<\/p>\n<p>Then, we use another internal interface to restore the recursion level when the thread acquires the lock again.<\/p>\n<p>wait() returns False if the <i>timeout<\/i> expires. Otherwise, it returns True.<\/p>\n<h4>4. wait_for(predicate, timeout=None) in Python Condition Object<\/h4>\n<p>This method waits until a condition becomes True. The <i>predicate<\/i> is a callable with a Boolean result. We may provide a <i>timeout<\/i> to specify a maximum time to wait.<\/p>\n<p>wait_for() is a utility method, and it can repeatedly make a call to wait() until the predicate satisfies, or until a timeout happens.<\/p>\n<p>It returns the predicate\u2019s last return value, and returns False if the method times out.<\/p>\n<p>With this method, the same rules apply as do to wait(). When we call it, the lock must be held, and acquires again on return. This evaluates the predicate with the lock held.<\/p>\n<h4>5. notify(n=1) in Python Condition Object<\/h4>\n<p>notify() wakes up a thread waiting on this condition, if there is any. When we call it, if the calling thread doesn\u2019t own the lock, this raises a RuntimeError.<\/p>\n<p>It wakes up a maximum of n threads that wait for the condition variable. If no threads wait, then it is a no-operation(NOP).<\/p>\n<p>If at least n threads wait, this implementation will wake exactly n threads up. But we can\u2019t rely on this behavior.<\/p>\n<p>An optimized implementation can occasionally wake more than n threads up.<\/p>\n<h4>6. notify_all() in Python Condition Object<\/h4>\n<p>This wakes up all threads that wait on this condition. So, this is like notify(), except that it wakes all waiting threads instead of exactly one.<\/p>\n<p>If at the time of calling it, if the calling thread doesn\u2019t own the lock, this raises a RuntimeError.<\/p>\n<h3>Python Semaphore Objects<\/h3>\n<p>Early Dutch computer scientist Edsger W. Dijkstra invented one of the oldest synchronization primitives. Instead of acquire() and release(), he used P() and V().<\/p>\n<p>What is a semaphore? It is a primitive that lets us manage an internal counter. Each call to acquire() decrements, and each call to release() decrements it.<\/p>\n<p>But let us tell you, the counter never goes below zero. When it is 0, acquire() blocks, and waits until a thread makes a call to release().<\/p>\n<p>Semaphores in Python Multithreading support CMP(Context Management Protocol).<\/p>\n<p>This is the class we have:<\/p>\n<p>class threading.Semaphore(value=1)<\/p>\n<p>It implements semaphore objects.<\/p>\n<p>A semaphore holds an atomic counter denoting the count of release() calls minus the count of acquire() calls, added to an initial value.acquire() blocks if needed until it can leave the counter non-negative and still return.<\/p>\n<p>The default value for the counter is 1.<\/p>\n<p>This class implements semaphore objects.<\/p>\n<p>A semaphore manages an atomic counter representing the number of release() calls minus the number of acquire() calls, plus an initial value.<\/p>\n<p>The acquire() method blocks if necessary until it can return without making the counter negative. If not given, value defaults to 1.<br \/>\n<i><\/i><\/p>\n<p><i>value<\/i> can serve as an initial value for the internal counter. The default for this is 1. If we pass a value less than 0, this raises a ValueError.<\/p>\n<p>It has the following methods:<\/p>\n<h4>1. acquire(blocking=True, timeout=None) in Python Semaphore<\/h4>\n<p>This acquires a semaphore. When we pass a <i>timeout<\/i> value other than None, it blocks for a maximum of <i>timeout<\/i> seconds.<\/p>\n<p>If in that interval, acquire() doesn\u2019t complete successfully, it returns False. Otherwise, it returns True.<\/p>\n<p>When we call it without arguments, the following cases may be:<\/p>\n<ul>\n<li>If, on entry, the internal counter is greater than zero, it decrements it by one, and then returns.<\/li>\n<li>If, on entry, the internal counter is zero, it blocks until a call to release() wakes it up. Now that the counter is greater than 0, it decrements it by 1, and then returns True. Each call to release() wakes exactly one thread. We cannot say what order this happens in.<\/li>\n<li>When we call it with <i>blocking<\/i> with a value of False, it doesn\u2019t block. And if a call without arguments blocks, then it returns False. Otherwise, it does the same as when called without arguments, and then returns True.<\/li>\n<\/ul>\n<h4>2. release() in Python Semaphore<\/h4>\n<p>This method releases a semaphore and increments the internal counter by 1. When, on entry, it is 0, and another thread waits for it to grow again, it wakes that thread up.<\/p>\n<p>We also have bounded semaphores:<\/p>\n<p>class threading.BoundedSemaphore(value=1)<\/p>\n<p>This class implements bounded semaphore objects. Such objects ensure that their current values do not exceed their initial values.<\/p>\n<p>It this happens, this raises a ValueError. Mostly, semaphores guard resources with limited capacity, for ex., a database server. Where the resource size is fixed, use a bounded semaphore.<\/p>\n<p>But if it releases the semaphore way too many times, then you may have a bug in your code. The default for this is 1.<\/p>\n<p>Let\u2019s take an example. The main thread initializes the semaphore before spawning any worker threads:<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; maxconnections=5\r\n&gt;&gt;&gt; pool_sema=threading.BoundedSemaphore(value=maxconnections)<\/pre>\n<p>Now that it is spawned, the worker threads call acquire() and release() when they must connect to the server:<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt;with pool_sema:\r\n     conn=connectdb()\r\n     try:\r\n        #use connection\r\n     finally:\r\n         conn.close()<\/pre>\n<p>Using a bounded semaphore lessens the chances of programming errors.<\/p>\n<h3>Python Event Objects<\/h3>\n<p>An extremely simple tool in Python Multithreading to communicate, it lets one thread play an event, and the other must wait for it.<\/p>\n<p>An event object deals an internal flag. The methods set() and clear() allow us to set and reset it to True and False, respectively. Until <i>flag<\/i> is True, wait() blocks.<\/p>\n<p>This is the class:<\/p>\n<p>class threading.Event<\/p>\n<p>This class implements event objects. An event handles a flag, and we can use the methods set() and clear() to set and reset it to True and False, respectively.<\/p>\n<p>Initially, the flag is False. wait() blocks it until it becomes True.<\/p>\n<p>It has the following methods:<\/p>\n<h4>1. is_set() in Python Event<\/h4>\n<p>If the internal flag is True, it returns True.<\/p>\n<h4>2. set() in Python Event<\/h4>\n<p>This method sets the internal flag to True, and wakes all threads waiting for it to become True. Once it is True, waiting threads do not block at all.<\/p>\n<h4>3. clear() in Python Event<\/h4>\n<p>This resets the internal flag to False. Eventually, waiting threads block until somebody calls set() to set the internal flag to True yet again.<\/p>\n<h4>4. wait(timeout=None) in Python Event<\/h4>\n<p>Until the internal flag is True, this method blocks. On entry, if it is True, it returns immediately. Otherwise, it blocks until another thread makes a call to set() to set the flag to True, or until<\/p>\n<p><i>timeout<\/i> happens.<\/p>\n<p>When a <i>timeout<\/i> exists and isn\u2019t now, make sure it\u2019s a floating-point number denoting a <i>timeout<\/i> for the operation in seconds or fractions.<\/p>\n<p>It returns True only if the internal flag is True- either before the call to wait(), or after. This way, wait() always returns True. However, if a <i>timeout<\/i> exists and the operation times out, it returns False.<\/p>\n<h3>Python Timer Objects<\/h3>\n<p>A timer denotes an action that should run only after a given amount of time; it is a timer in Python Multithreading.<\/p>\n<p>This is a subclass of Thread, and we can also use it to learn how to create our own threads.<\/p>\n<p>When we call start() on a thread, a timer starts with it. We can stop it before it begins if we call cancel() on it. Before executing, a timer waits for some interval; this may differ from the interval we specify.<\/p>\n<p>Take an example:<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; def hello():\r\n    print(\"Hello\")\r\n&gt;&gt;&gt; t=threading.Timer(30.0,hello)\r\n&gt;&gt;&gt; t.start()<\/pre>\n<p>This is the class:<\/p>\n<p>class threading.Timer(interval, function, args=None, kwargs=None)<\/p>\n<p>It creates a timer that runs a function(with arguments args and kwargs) after <i>interval<\/i> seconds. When args is None, it uses an empty list.<\/p>\n<p>This is the default. And when kwargs is None, it uses an empty dict. This is a default too.<\/p>\n<p>It has one method:<\/p>\n<h4>1. cancel() in Python Timer<\/h4>\n<p>This stops the timer and then cancels its action. This only works if the timer is waiting.<\/p>\n<p>Now the last in Python Multithreading is Barrier Objects.<\/p>\n<h3>Barrier Objects<\/h3>\n<p>Barrier is a simple synchronization primitive for a fixed number of threads that must wait for each other.<\/p>\n<p>Each thread tries to pass the barrier by making a call to wait; it blocks until all threads have done this. Then, the threads release simultaneously.<\/p>\n<p>You can reuse a barrier any number of times for the same number of threads. Let\u2019s take an example.<\/p>\n<p>A way to synchronize a client and server thread is:<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; b=threading.Barrier(2,timeout=5)\r\n&gt;&gt;&gt; def server():\r\n      start_server()\r\n      b.wait()\r\n      while True:\r\n              connection = accept_connection() \r\n              process_server_connection(connection)<\/pre>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; def client():\r\n     b.wait()\r\n     while True:    \r\n             connection = make_connection()\r\n             process_client_connection(connection)<\/pre>\n<p>This is the class:<\/p>\n<p>class threading.Barrier(parties, action=None, timeout=None)<\/p>\n<p>Barrier creates a barrier object for <i>a<\/i> number of threads. When we do pass <i>action<\/i>, it is a callable that a thread will call when we release it.<\/p>\n<p>Finally, <i>timeout<\/i> is a default value for timeout if we don\u2019t specify the same for wait().<\/p>\n<p>It has the following methods:<\/p>\n<div id=\"attachment_36536\" style=\"width: 1210px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Barrier-Objects-in-Python-01.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-36536\" class=\"size-full wp-image-36536\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Barrier-Objects-in-Python-01.jpg\" alt=\"Python Multithreading - Threads, Locks, Functions of Multithreading\" width=\"1200\" height=\"630\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Barrier-Objects-in-Python-01.jpg 1200w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Barrier-Objects-in-Python-01-150x79.jpg 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Barrier-Objects-in-Python-01-300x158.jpg 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Barrier-Objects-in-Python-01-768x403.jpg 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Barrier-Objects-in-Python-01-1024x538.jpg 1024w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Barrier-Objects-in-Python-01-520x273.jpg 520w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><p id=\"caption-attachment-36536\" class=\"wp-caption-text\">Python Multithreading Tutorial &#8211; Python Barrier Object<\/p><\/div>\n<h4>1. wait(timeout=None) in Python Barrier<\/h4>\n<p>wait() passes the barrier. Once all thread parties have called wait(), they all release together.<\/p>\n<p>If we do pass a value for <i>timeout<\/i>, it uses this one, no matter whether we provided a value for the same to the class constructor.<\/p>\n<p>It returns any integer value from 0 to parties-1. This is different for each thread. You can use this to choose a thread to do special housekeeping.<\/p>\n<p>Take an example:<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; i=barrier.wait()\r\n&gt;&gt;&gt; if i==0:\r\n            #Only one thread must print this\r\n            print(\"passed the barrier\")<\/pre>\n<p>If we provided an action to the constructor, one thread calls it before releasing. If this raises an error, the barrier sinks into a \u2018broken\u2019 state.<\/p>\n<p>The same happens if the call times out.<\/p>\n<p>Finally, wait() may raise a BrokenBarrierError if the barrier breaks or resets as a thread waits.<\/p>\n<h4>2. reset() in Python Barrier<\/h4>\n<p>This function resets the barrier to its default, empty state. Any waiting threads receive a BrokenBarrierError.<\/p>\n<p>reset() may need external synchronization if other threads with unknown states exist. If it breaks a barrier, just create a new one.<\/p>\n<h4>3. abort() in Python Barrier<\/h4>\n<p>abort() puts a barrier into a \u2018broken\u2019 state. Consequently, active\/future calls to wait() fail with a BrokenBarrierError.<\/p>\n<p>To avoid deadlocking an application, we may need to abort it. This is one use-case.<\/p>\n<p>Try to create the barrier with a sensible value for <i>timeout,<\/i> so it automatically guards against a thread going haywire.<\/p>\n<h4>4. parties in Python Barrier<\/h4>\n<p>This returns the number of threads we need to pass the barrier.<\/p>\n<h4>5. n_waiting in Python Barrier<\/h4>\n<p>This returned the number of threads that currently wait in the barrier.<\/p>\n<h4>6. broken in Python Barrier<\/h4>\n<p>This is a Boolean value that is True if the barrier is in a \u2018broken\u2019 state.<\/p>\n<p>Check out this exception that Barrier may raise:<\/p>\n<p>exception threading.BrokenBarrierError<\/p>\n<p>This is a subclass of RuntimeError, and it raises if a Barrier object resets or breaks.<\/p>\n<p>Now lets learn using locks, conditions, and semaphores in the with-statement in the last topic of our Python Multithreading Tutorial.<\/p>\n<h3>Using locks, conditions, and semaphores in the with-statement<\/h3>\n<p>If an object in this module has acquire() and release(), we can use it as a context manager for a with-statement.<\/p>\n<p>When it enters the block, it calls acquire(), and when it exits it, it calls release().<\/p>\n<p>This is the syntax for the same:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">with some_lock:\r\n        #do something<\/pre>\n<p>This is the same as:<\/p>\n<pre class=\"EnlighterJSRAW\">&gt;&gt;&gt; some_lock.acquire()\r\n&gt;&gt;&gt; try:\r\n      #do something\r\nfinally:\r\n       some_lock.release()<\/pre>\n<p>We can currently use Lock, RLock, Condition, Semaphore, and BoundedSemaphore objects as context managers for with-statements.<\/p>\n<p>So, this was all about Python Multithreading Tutorial. Hope you like our explanation.<\/p>\n<h3>Python Interview Questions on Multi-threading<\/h3>\n<ol>\n<li>What is Python Multithreading? Explain with an example.<\/li>\n<li>How is Multithreading achieved in Python?<\/li>\n<li>What is the use of Multithreading in Python?<\/li>\n<li>Which is better, multithreading or multiprocessing in Python?<\/li>\n<li>How many threads can you have in Python?<\/li>\n<\/ol>\n<h3>Conclusion<\/h3>\n<p>This is all about Python Multithreading with Example, Functions of Python Multithreading, Thread &#8211; Local Data, Thread Objects in Python Multithreading, and <span id=\"13_Using_locks_conditions_and_semaphores_in_the_with-statement\">Using locks, conditions, and semaphores in the with-statement in Python Multithreading.\u00a0<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this lesson, we\u2019ll learn to implement Python Multithreading with an example. We will use the module \u2018threading\u2019 for this. We will also have a look at the Functions of Python Multithreading, Thread &#8211;&#46;&#46;&#46;<\/p>\n","protected":false},"author":5,"featured_media":31026,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[46],"tags":[104,1637,2866,4973,8368,10703,11612,12718,14711,14713,14735,15290],"class_list":["post-12071","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-python","tag-event-objects","tag-barrier-objects","tag-condition-objects","tag-functions-in-python-multithreading","tag-lock-objects","tag-python-multithreading","tag-rlock-objects","tag-semaphore-objects","tag-thread-local-data","tag-thread-objects","tag-timer-objects","tag-using-locks"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Python Multithreading - Threads, Locks, Functions of Multithreading - DataFlair<\/title>\n<meta name=\"description\" content=\"Python Multithreading with Example-Functions of Multithreading in Python,Condition, Semaphore,Event,Timer,RLock Objects in Python,Python Thread &amp; local Data\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/data-flair.training\/blogs\/python-multithreading\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Python Multithreading - Threads, Locks, Functions of Multithreading - DataFlair\" \/>\n<meta property=\"og:description\" content=\"Python Multithreading with Example-Functions of Multithreading in Python,Condition, Semaphore,Event,Timer,RLock Objects in Python,Python Thread &amp; local Data\" \/>\n<meta property=\"og:url\" content=\"https:\/\/data-flair.training\/blogs\/python-multithreading\/\" \/>\n<meta property=\"og:site_name\" content=\"DataFlair\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/DataFlairWS\/\" \/>\n<meta property=\"article:published_time\" content=\"2018-03-28T06:32:09+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-24T11:14:58+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Multithreading-in-Python-01-1.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"DataFlair Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@DataFlairWS\" \/>\n<meta name=\"twitter:site\" content=\"@DataFlairWS\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"DataFlair Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"24 minutes\" \/>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Python Multithreading - Threads, Locks, Functions of Multithreading - DataFlair","description":"Python Multithreading with Example-Functions of Multithreading in Python,Condition, Semaphore,Event,Timer,RLock Objects in Python,Python Thread & local Data","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/data-flair.training\/blogs\/python-multithreading\/","og_locale":"en_US","og_type":"article","og_title":"Python Multithreading - Threads, Locks, Functions of Multithreading - DataFlair","og_description":"Python Multithreading with Example-Functions of Multithreading in Python,Condition, Semaphore,Event,Timer,RLock Objects in Python,Python Thread & local Data","og_url":"https:\/\/data-flair.training\/blogs\/python-multithreading\/","og_site_name":"DataFlair","article_publisher":"https:\/\/www.facebook.com\/DataFlairWS\/","article_published_time":"2018-03-28T06:32:09+00:00","article_modified_time":"2026-04-24T11:14:58+00:00","og_image":[{"width":1200,"height":628,"url":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Multithreading-in-Python-01-1.jpg","type":"image\/jpeg"}],"author":"DataFlair Team","twitter_card":"summary_large_image","twitter_creator":"@DataFlairWS","twitter_site":"@DataFlairWS","twitter_misc":{"Written by":"DataFlair Team","Est. reading time":"24 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/data-flair.training\/blogs\/python-multithreading\/#article","isPartOf":{"@id":"https:\/\/data-flair.training\/blogs\/python-multithreading\/"},"author":{"name":"DataFlair Team","@id":"https:\/\/data-flair.training\/blogs\/#\/schema\/person\/7f83c342f5d1632d6f7b4b0b0f447823"},"headline":"Python Multithreading &#8211; Threads, Locks, Functions of Multithreading","datePublished":"2018-03-28T06:32:09+00:00","dateModified":"2026-04-24T11:14:58+00:00","mainEntityOfPage":{"@id":"https:\/\/data-flair.training\/blogs\/python-multithreading\/"},"wordCount":5188,"commentCount":0,"publisher":{"@id":"https:\/\/data-flair.training\/blogs\/#organization"},"image":{"@id":"https:\/\/data-flair.training\/blogs\/python-multithreading\/#primaryimage"},"thumbnailUrl":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Multithreading-in-Python-01-1.jpg","keywords":[". Event Objects","Barrier Objects","Condition Objects","Functions in Python Multithreading","Lock Objects","Python Multithreading","RLock Objects","Semaphore Objects","Thread - Local Data","Thread Objects","Timer Objects","Using locks"],"articleSection":["Python Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/data-flair.training\/blogs\/python-multithreading\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/data-flair.training\/blogs\/python-multithreading\/","url":"https:\/\/data-flair.training\/blogs\/python-multithreading\/","name":"Python Multithreading - Threads, Locks, Functions of Multithreading - DataFlair","isPartOf":{"@id":"https:\/\/data-flair.training\/blogs\/#website"},"primaryImageOfPage":{"@id":"https:\/\/data-flair.training\/blogs\/python-multithreading\/#primaryimage"},"image":{"@id":"https:\/\/data-flair.training\/blogs\/python-multithreading\/#primaryimage"},"thumbnailUrl":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Multithreading-in-Python-01-1.jpg","datePublished":"2018-03-28T06:32:09+00:00","dateModified":"2026-04-24T11:14:58+00:00","description":"Python Multithreading with Example-Functions of Multithreading in Python,Condition, Semaphore,Event,Timer,RLock Objects in Python,Python Thread & local Data","breadcrumb":{"@id":"https:\/\/data-flair.training\/blogs\/python-multithreading\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/data-flair.training\/blogs\/python-multithreading\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/data-flair.training\/blogs\/python-multithreading\/#primaryimage","url":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Multithreading-in-Python-01-1.jpg","contentUrl":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/03\/Multithreading-in-Python-01-1.jpg","width":1200,"height":628,"caption":"Python Multithreading"},{"@type":"BreadcrumbList","@id":"https:\/\/data-flair.training\/blogs\/python-multithreading\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Blog Home","item":"https:\/\/data-flair.training\/blogs\/"},{"@type":"ListItem","position":2,"name":"Python Tutorials","item":"https:\/\/data-flair.training\/blogs\/category\/python\/"},{"@type":"ListItem","position":3,"name":"Python Multithreading &#8211; Threads, Locks, Functions of Multithreading"}]},{"@type":"WebSite","@id":"https:\/\/data-flair.training\/blogs\/#website","url":"https:\/\/data-flair.training\/blogs\/","name":"DataFlair","description":"Learn Today. Lead Tomorrow.","publisher":{"@id":"https:\/\/data-flair.training\/blogs\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/data-flair.training\/blogs\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/data-flair.training\/blogs\/#organization","name":"DataFlair","url":"https:\/\/data-flair.training\/blogs\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/data-flair.training\/blogs\/#\/schema\/logo\/image\/","url":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2016\/07\/Data-Flair.png","contentUrl":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2016\/07\/Data-Flair.png","width":106,"height":48,"caption":"DataFlair"},"image":{"@id":"https:\/\/data-flair.training\/blogs\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/DataFlairWS\/","https:\/\/x.com\/DataFlairWS","https:\/\/www.linkedin.com\/company\/dataflair-web-services-pvt-ltd\/","https:\/\/www.youtube.com\/user\/DataFlairWS"]},{"@type":"Person","@id":"https:\/\/data-flair.training\/blogs\/#\/schema\/person\/7f83c342f5d1632d6f7b4b0b0f447823","name":"DataFlair Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/4cf3a74600d131330b8c481d519afd1574093ed89f6d3396a95393ad223eb7cd?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/4cf3a74600d131330b8c481d519afd1574093ed89f6d3396a95393ad223eb7cd?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4cf3a74600d131330b8c481d519afd1574093ed89f6d3396a95393ad223eb7cd?s=96&d=mm&r=g","caption":"DataFlair Team"},"description":"DataFlair Team creates expert-level guides on programming, Java, Python, C++, DSA, AI, ML, data Science, Android, Flutter, MERN, Web Development, and technology. Our goal is to empower learners with easy-to-understand content. Explore our resources for career growth and practical learning.","url":"https:\/\/data-flair.training\/blogs\/author\/dfteam1\/"}]}},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/posts\/12071","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/comments?post=12071"}],"version-history":[{"count":16,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/posts\/12071\/revisions"}],"predecessor-version":[{"id":147857,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/posts\/12071\/revisions\/147857"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/media\/31026"}],"wp:attachment":[{"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/media?parent=12071"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/categories?post=12071"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/tags?post=12071"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}