Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1790179
  • 博文数量: 297
  • 博客积分: 285
  • 博客等级: 二等列兵
  • 技术积分: 3006
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-06 22:04
个人简介

Linuxer, ex IBMer. GNU https://hmchzb19.github.io/

文章分类

全部博文(297)

文章存档

2020年(11)

2019年(15)

2018年(43)

2017年(79)

2016年(79)

2015年(58)

2014年(1)

2013年(8)

2012年(3)

分类: Python/Ruby

2016-04-22 13:43:25

多线程真是太复杂了,C语言里面,就是不返回任何值的void *的函数。但是当我看到那一本a little book of semaphore. 就想死
更别说还有mutex, spinlock, condition ,复杂啊。
看python 的threading module 好像要简单一些,但是毕竟也不知道Cpython是怎么实现的。
anyway,先存点代码留待以后慢慢看。
1. 这个代码我注视了join, main-thread 会默认等待非daemon 的线程。所以join 感觉并不需要。

点击(此处)折叠或打开

  1. def thread_1():
  2.     def countdown(n):
  3.         while n > 0:
  4.             print('T -minus ',n)
  5.             n-=1
  6.             time.sleep(1)

  7.     #create and launch a thread

  8.     t=threading.Thread(target=countdown,args=(10,))
  9.     t.start()
  10.     while True:
  11.         if t.is_alive():
  12.             print("Still running")
  13.             time.sleep(1)
  14.         else:
  15.             print('Completed')
  16.             break

  17.     #t.join()

  18. thread_1()
2. 从主线程去停止其他线程,这难道是C语言的signal 吗?不清楚

点击(此处)折叠或打开

  1. class CountdownTask:
  2.     def __init__(self):
  3.         self._running=True

  4.     def terminate(self):
  5.         self._running=False

  6.     def run(self,n):
  7.         while self._running and n >0:
  8.             print('T - minus',n)
  9.             n-=1
  10.             time.sleep(1)

  11. def thread2():
  12.     c = CountdownTask()
  13.     t = threading.Thread(target=c.run, args=(10,))
  14.     t.start()
  15.     if t.is_alive():
  16.         print("Still running")
  17.     else:
  18.         print('Completed')
  19.     c.terminate() # Signal termination
  20.     t.join() # Wait for actual termination (if needed)


  21. #thread2()
3. Event 做线程通信。只有4个方法
主线程调用wait ,等待子线程set()之后 主线程继续执行

点击(此处)折叠或打开

  1. is_set():Return true if and only if the internal flag is true.
  2. set():Set the internal flag to true. All threads waiting for it to become true are awakened. Threads that call wait() once the flag is true will not block at all.
  3. clear():Reset the internal flag to false
  4. wait(timeout=None): Block until the internal flag is true. If the internal flag is true on entry, return immediately. Otherwise, block until another thread calls set() to set the flag to true, or until the optional timeout occurs.

  5. logging.basicConfig(level=logging.DEBUG,format='%(asctime)s (%(threadName)-10s) %(message)s',)

  6. def thread3():
  7.     # Code to execute in an independent thread
  8.     def countdown(n,started_evt):
  9.         print('countdown starting')
  10.         started_evt.set()
  11.         while n>0:
  12.             logging.debug('T-minus {}'.format(n))
  13.             n-=1
  14.             time.sleep(1)

  15.     # Create the event object that will be used to signal startup
  16.     started_evt=threading.Event()

  17.     ## Launch the thread and pass the startup event
  18.     logging.debug('Launching countdown')
  19.     t=threading.Thread(target=countdown,args=(10,started_evt))
  20.     t.start()
  21.     logging.debug("Event is set or not {}:".format(started_evt.is_set()))
  22.     #wait for the thread to start
  23.     started_evt.wait()
  24.     logging.debug('Countdwon is running')

  25. thread3()
4.  对于set daemon的线程,应该显式的join,去等待。
默认join 会一直blocking, 但是可以传给它一个float。 If the thread does not complete within the timeout period, join() returns anyway

点击(此处)折叠或打开

  1. def determine_current_thread():
  2.     def daemon():
  3.         logging.debug("starting")
  4.         time.sleep(2)
  5.         logging.debug("Exiting")

  6.     def non_daemon():
  7.         logging.debug("starting")
  8.         logging.debug("Exiting")

  9.     d=threading.Thread(name="daemon",target=daemon)
  10.     d.setDaemon(True)

  11.     t=threading.Thread(name="non-daemon",target=non_daemon)

  12.     d.start()
  13.     t.start()

  14.     t.join()
  15.     print("d.isAlive() {}".format(d.isAlive()))
  16.     #d.join(timeout=1)
  17.     d.join()

  18. #determine_current_thread()

5. 使用enumerate 获取线程的列表,不能对主线程join,会造成死锁。

点击(此处)折叠或打开

  1. #enumerate() returns a list of active Thread instances. The list includes the current thread,
  2. #since joining the current thread is not allowed (it introduces a deadlock situation), it must be skipped
  3. def thread_enumerate():
  4.     def worker():
  5.         #threwad worker function
  6.         t=threading.currentThread()
  7.         pause=random.randint(1,5)
  8.         logging.debug("sleeping {}".format(pause))
  9.         time.sleep(pause)
  10.         logging.debug("ending")
  11.         return

  12.     for i in range(3):
  13.         t=threading.Thread(target=worker)
  14.         t.setDaemon(True)
  15.         t.start()

  16.     main_thread=threading.currentThread()
  17.     for t in threading.enumerate():
  18.         if t is main_thread:
  19.             continue
  20.         logging.debug("joing {}".format(t.getName()))
  21.         t.join()

  22. #thread_enumerate()
6. 仍然是个使用Event 做线程signal 传递的例子。

点击(此处)折叠或打开

  1. #signal between threads, easy way to do this is with Event object
  2. # An Event manages an internal flag that callers can either set() or clear(). Other threads can wait() for the flag to be set(),
  3. #effectively blocking progress until allowed to continue
  4. #In this example, wait_for_event_timeout() checks the event status without blocking indefinitely.
  5. #The wait_for_event() blocks on the call to wait(), which does not return until the event status changes.
  6. def signal_event():
  7.     def wait_for_event(e):
  8.         #wait for the event to be set before doing any thing
  9.         logging.debug("wait_for_event starting")
  10.         event_is_set=e.wait()
  11.         logging.debug("event set: {}".format(event_is_set))

  12.     def wait_for_event_timeout(e,t):
  13.         #wait t seconds and then timeout
  14.         while not e.isSet():
  15.             logging.debug("Waiting_for_event_timeout starting")
  16.             event_is_set=e.wait(t)
  17.             logging.debug("event set {}".format(event_is_set))
  18.             if event_is_set:
  19.                 logging.debug("processing event")
  20.             else:
  21.                 logging.debug("doing other work")
  22.     
  23.     e=threading.Event()
  24.     t1=threading.Thread(name="block",target=wait_for_event,args=(e,))
  25.     t1.start()

  26.     t2=threading.Thread(name="non-block",target=wait_for_event_timeout,args=(e,2))
  27.     t2.start()

  28.     logging.debug("Waiting before calling Event.set()")
  29.     time.sleep(3)
  30.     e.set()
  31.     logging.debug("Event is set")

  32. signal_event()
Bonus:
使用cProfile 看看都做了些啥。

点击(此处)折叠或打开

  1. import cProfile
  2. cProfile.run('signal_event()')

点击(此处)折叠或打开

  1. (block ) wait_for_event starting
  2. (non-block ) Waiting_for_event_timeout starting
  3. (MainThread) Waiting before calling Event.set()
  4. (non-block ) event set False
  5. (non-block ) doing other work
  6. (non-block ) Waiting_for_event_timeout starting
  7. (MainThread) Event is set
  8. (block ) event set: True
  9.          228 function calls in 3.021 seconds

  10.    Ordered by: standard name

参考资料:





阅读(1930) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~