如何组合线程安全操作并使它们成为原子操作?
How to compose thread safe operations and make them atomic?
让我们采用线程安全的方式 class,例如 LinkedBlockingDeque
:
BlockingQueue<Task> taskQueue = new LinkedBlockingDeque<Task>();
我知道 take
和 put
等操作是线程安全的,因此它们尊重 happened-before 关系。
但是如果我想组合一些操作使它们成为原子操作呢?
像这样:
if(taskQueue.size() == 1) {
/*Do a lot of things here, but I do not want other threads
to change the size of the queue here with take or put*/
}
//taskQueue.size() must still be equal to 1
如果它不是线程安全的class,我可以这样做:
synchronized(taskQueue) {
if(taskQueue.size() == 1) {
/*Do a lot of things here, but I do not want other threads
to change the size of the queue here with take or put*/
}
//taskQueue.size() must still be equal to 1
}
但没那么简单,我不认为take
和put
的实现使用对象锁。
你如何处理这个 scanario?
How do you handle this scenario?
一般来说,如果不使用某种外部锁定,就无法对并发数据结构进行 "compose" 操作。当你这样做时,你重新引入了你试图通过使用并发数据结构来避免的并发瓶颈。
在这种情况下,你是对的。 LinkedBlockingDeque
class 使用私有锁对象进行同步等。
让我们采用线程安全的方式 class,例如 LinkedBlockingDeque
:
BlockingQueue<Task> taskQueue = new LinkedBlockingDeque<Task>();
我知道 take
和 put
等操作是线程安全的,因此它们尊重 happened-before 关系。
但是如果我想组合一些操作使它们成为原子操作呢? 像这样:
if(taskQueue.size() == 1) {
/*Do a lot of things here, but I do not want other threads
to change the size of the queue here with take or put*/
}
//taskQueue.size() must still be equal to 1
如果它不是线程安全的class,我可以这样做:
synchronized(taskQueue) {
if(taskQueue.size() == 1) {
/*Do a lot of things here, but I do not want other threads
to change the size of the queue here with take or put*/
}
//taskQueue.size() must still be equal to 1
}
但没那么简单,我不认为take
和put
的实现使用对象锁。
你如何处理这个 scanario?
How do you handle this scenario?
一般来说,如果不使用某种外部锁定,就无法对并发数据结构进行 "compose" 操作。当你这样做时,你重新引入了你试图通过使用并发数据结构来避免的并发瓶颈。
在这种情况下,你是对的。 LinkedBlockingDeque
class 使用私有锁对象进行同步等。