Threading
Thread
- target, the callable object to be invoked by the run() method
- args, the argument tuple for the target invocation
- kwargs, a dictionary of keyword arguments for the target invocation
- start(), start thread
- run(), implement callable object
- join(), wait until the thread terminates
- getName(), get thread's name
Threading
- currentThreading(), get the current thread
#!/usr/bin/python
import threading
def worker(i):
"""thread worker function"""
print 'Hello World!', i
threads = []
#Create threads
for i in range(5):
threads.append(threading.Thread(target=worker, args = (i, )));
#Start theads
for t in threads:
t.start()
#Join theads
for t in threads:
print 'Join', t.ident, t.getName()
t.join()
print 'End of program'
#!/usr/bin/python
import threading
import logging
def worker(i):
"""thread worker function"""
logging.debug(str(threading.currentThread().getName()) + ' Start ...');
print 'Hello World!', i
logging.debug(threading.currentThread().getName() + ' End ...');
logging.basicConfig(format='[%(levelname)s] (%(threadName)-10s): %(message)s', level=logging.DEBUG);
threads = []
#Create threads
for i in range(5):
threads.append(threading.Thread(target=worker, args = (i, )));
#Start theads
for t in threads:
t.start()
#Join theads
for t in threads:
print 'Join', t.ident, t.getName()
t.join()
print 'End of program'
Daemon thread
- daemon threads are terminated when the main program exits
- non-daemon threads are terminated only when they finish their tasks
#!/usr/bin/python
import threading
import logging
def daemon():
logging.debug('Daemon thead starts ...');
logging.debug('Daemon thead ends ...');
def nonDaemon():
logging.debug('None-daemon thead starts ...');
logging.debug('None-daemon thead ends ...');
logging.basicConfig(format='[%(levelname)s] (%(threadName)-10s): %(message)s', level=logging.DEBUG);
d = threading.Thread(target=daemon);
d.setDaemon(True)
nd = threading.Thread(target=nonDaemon);
d.start();
nd.start();
#d.join();
#nd.join();
print 'End of program'
Enumerate threads
#!/usr/bin/python
import threading
import logging
import time
def worker(i):
"""thread worker function"""
print 'Hello World!', i
time.sleep(1);
logging.basicConfig(level=logging.DEBUG)
threads = []
#Create threads
for i in range(5):
threads.append(threading.Thread(target=worker, args = (i, )));
#Start theads
for t in threads:
t.start()
#Enumerate threads
for t in threading.enumerate():
logging.debug('Name: %s ...', t.getName());
#Join theads
for t in threads:
print 'Join', t.ident, t.getName()
t.join()
print 'End of program'
Timer
#!/usr/bin/python
import threading
import logging
def worker():
"""thread worker function"""
logging.debug('Hello World! %s', threading.currentThread().getName())
logging.basicConfig(level=logging.DEBUG)
threads = []
#Create threads
t_1 = threading.Timer(1, worker);
t_2 = threading.Timer(1, worker);
t_1.start();
t_2.start();
#Join theads
for t in threading.enumerate():
if t is threading.currentThread():
continue
logging.debug('Join %d %s', t.ident, t.getName())
t.join()
print 'End of program'
Event
- isSet()
- set()
- clear()
- wait()
#!/usr/bin/python
import threading
import logging
def event_1(e):
logging.debug('Waiting for the event happens ...');
e.wait();
logging.debug('Hello World!');
def event_2(e):
logging.debug('Start the event ...');
e.set();
logging.basicConfig(level=logging.DEBUG);
e = threading.Event();
t_1 = threading.Thread(target=event_1, args=(e, ));
t_2 = threading.Thread(target=event_2, args=(e, ));
t_1.start();
t_2.start();
Lock
- acquire(), request lock, if not available, block the current thread until the lock is available
- acquire(0), request lock, if not available, do not block
- release(), release lock
- Python’s built-in data structures, such as lists, dictionaries, etc., are thread-safe
- Other data structures implemented in Python, such as integers and floats, don’t have that protection
#!/usr/bin/python
import threading
import logging
num = 0;
lock = threading.Lock();
def increase(lock):
lock.acquire()
logging.debug('Call increase() in %s ...', threading.currentThread().getName());
global num;
num += 1;
logging.debug('End up thread %s ...', threading.currentThread().getName());
lock.release()
logging.basicConfig(level=logging.DEBUG);
threads = []
for i in xrange(5):
threads.append(threading.Thread(target=increase, args=(lock, )));
for t in threads:
t.start();
for t in threads:
t.join();
print num
RLock
- A reentrant lock is a synchronization primitive that may be acquired multiple times by the same thread
import threading
lock = threading.RLock()
print 'First try :', lock.acquire()
print 'Second try:', lock.acquire()
With
#!/usr/bin/python
import threading
import logging
num = 0;
lock = threading.Lock();
def increase(lock):
with lock:
logging.debug('Call increase() in %s ...', threading.currentThread().getName());
global num;
num += 1;
logging.debug('End up thread %s ...', threading.currentThread().getName());
logging.basicConfig(level=logging.DEBUG);
threads = []
for i in xrange(5):
threads.append(threading.Thread(target=increase, args=(lock, )));
for t in threads:
t.start();
for t in threads:
t.join();
print num
Condition
import logging
import threading
import time
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s (%(threadName)-2s) %(message)s',
)
def consumer(cond, l):
logging.debug('Starting consumer thread %s', threading.currentThread().getName())
t = threading.currentThread()
with cond:
cond.wait()
logging.debug('Resource is available to consumer')
print l
l[0] = 0;
def producer(cond, l):
"""set up the resource to be used by the consumer"""
logging.debug('Starting producer thread')
with cond:
l[0] = 100;
logging.debug('Making resource available')
cond.notifyAll()
condition = threading.Condition()
l = range(10);
c1 = threading.Thread(name='c1', target=consumer, args=(condition, l))
c2 = threading.Thread(name='c2', target=consumer, args=(condition, l))
p = threading.Thread(name='p', target=producer, args=(condition, l))
c1.start()
c2.start()
time.sleep(2)
p.start()
Semaphore
- Limist the number of threads that are able to access the shared resource at the same time
import logging
import random
import threading
import time
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s (%(threadName)-2s) %(message)s',
)
def worker(s):
with s:
logging.debug('Thread: %s ...', threading.currentThread().getName());
time.sleep(1)
s = threading.Semaphore(2)
for i in range(4):
t = threading.Thread(target=worker, name=str(i), args=(s, ))
t.start()
Reference