Queue.Queue vs collections.deque
2016-05-10 23:11
639 查看
Queue.Queue
vs. collections.deque
up vote78down votefavorite 22 | I need a queue which multiple threads can put stuff into, and multiple threads may read from. Python has at least two queue classes, Queue.Queue and collections.deque, with the former seemingly using the latter internally. Both claim to be thread-safe in the documentation. However, the Queue docs also state: collections.deque is an alternative implementation of unbounded queues with fast atomic append() and popleft() operations that do not require locking. Which I guess I don't quite unterstand: Does this mean deque isn't fully thread-safe after all? If it is, I may not fully understand the difference between the two classes. I can see that Queue adds blocking functionality. On the other hand, it loses some deque features like support for the in-operator. Accessing the internal deque object directly, is x in Queue().deque thread-safe? Also, why does Queue employ a mutex for it's operations when deque is thread-safe already? python thread-safety queue
| ||||
a comment |
5 Answers
activeoldestvotesup vote131down voteaccepted | Queue.Queueand collections.dequeserve different purposes. Queue.Queue is intended for allowing different threads to communicate using queued messages/data, whereas collections.dequeis simply intended as a datastructure. That's why Queue.Queuehas methods like put_nowait(), get_nowait(), and join(), whereas collections.dequedoesn't. Queue.Queueisn't intended to be used as a collection, which is why it lacks the likes of the inoperator. It boils down to this: if you have multiple threads and you want them to be able to communicate without the need for locks, you're looking for Queue.Queue; if you just want a queue or a double-ended queue as a datastructure, use collections.deque. Finally, accessing and manipulating the internal deque of a Queue.Queueis playing with fire - you really don't want to be doing that.
| ||||||||||||||||||||
a comment |
up vote14down vote | If all you're looking for is a thread-safe way to transfer objects between threads, then both would work (both for FIFO and LIFO). For FIFO:Queue.put()and Queue.get()are thread-safe deque.append()and deque.popleft()are thread-safe Note: Other operations on dequemight not be thread safe, I'm not sure. dequedoes not block on pop()or popleft()so you can't base your consumer thread flow on blocking till a new item arrives. However, it seems that deque has a significant efficiency advantage. Here are some benchmark results in seconds using CPython 2.7.3 for inserting and removing 100k items deque 0.0747888759791 Queue 1.60079066852 Here's the benchmark code: import time import Queue import collections q = collections.deque() t0 = time.clock() for i in xrange(100000): q.append(1) for i in xrange(100000): q.popleft() print 'deque', time.clock() - t0 q = Queue.Queue(200000) t0 = time.clock() for i in xrange(100000): q.put(1) for i in xrange(100000): q.get() print 'Queue', time.clock() - t0
| ||||||||||||
a comment |
up vote2down vote | dequeis thread-safe. "operations that do not require locking" means that you don't have to do the locking yourself, the dequetakes care of it. Taking a look at the Queuesource, the internal deque is called self.queueand uses a mutex for accessors and mutations, so Queue().queueis not thread-safe to use. If you're looking for an "in" operator, then a deque or queue is possibly not the most appropriate data structure for your problem.
| ||||||||||||
a comment |
up vote1down vote | For information there is a Python ticket referenced for deque thread-safety (https://bugs.python.org/issue15329). Title "clarify which deque methods are thread-safe" Bottom line here: https://bugs.python.org/issue15329#msg199368 The deque's append(), appendleft(), pop(), popleft(), and len(d) operations are thread-safe in CPython. The append methods have a DECREF at the end (for cases where maxlen has been set), but this happens after all of the structure updates have been made and the invariants have been restored, so it is okay to treat these operations as atomic. Anyway, if you are not 100% sure and you prefer reliability over performance, just put a like Lock ;) |
相关文章推荐
- UIKIT点击事件中的职责链模式
- nessue6.6.2安装与离线激活
- UE4:旋转导致包围球体半径变化
- STL系列之三 queue 单向队列
- EasyUI学习笔记
- Glib学习(3) 双端队列 Double-ended Queues
- 一款FireBird3的GUI编辑器:FireBird Maestro V15.11.0.4
- iOS开发之基础视图——UITextField
- iOS开发 - 第01篇 - UI基础 - 04 - 超级猜图
- UIImage加载图片的方式以及Images.xcassets对于加载方法的影响
- 解决IOS8.1中UIActionSheet与UIPickerView不兼容
- Resolve Gradle Build Running stuck on Ubuntu 14
- 图形用户界面GUI
- j2ee四大作用域pagecontext,request,session,ServletContext
- iOS开发之基础视图——UIButton
- Ext中关于Ext.QuickTips.init()的使用
- UITabBar
- uva 12100 Printer Queue
- UISegmentedControl
- finished with non-zero exit value 2