我正在尝试使用以整数排队的信号量来实现线程安全队列。目前,这不是线程安全的。在同步方面,我必须添加什么以使其成为线程安全的队列?
我尝试在队列上使用同步块,以便同时在队列中只允许一个线程,但这似乎不起作用,或者我滥用了它们。我应该同步什么?我有一个单独的类,该类不断通过维护线程进行附加和删除。
class ThreadSafeQueue {
var queue = List[Int]()
val semaphore = new Semaphore(0)
def append(num: Int): Unit = {
queue = queue ::: List(num)
semaphore.release()
}
def dequeue(): Int = {
semaphore.acquire()
val n = queue.head
queue = queue.tail
n
}
}
答案 0 :(得分:1)
为确保线程安全,应将访问队列的代码放在synchronized
块中,如下所示。
import java.util.concurrent.Semaphore
class ThreadSafeQueue {
var queue = List[Int]()
val semaphore = new Semaphore(0)
def append(num: Int): Unit = {
synchronized {
queue = queue ::: List(num)
}
semaphore.release()
}
def dequeue(): Int = {
semaphore.acquire()
synchronized {
val n = queue.head
queue = queue.tail
n
}
}
}
一些注意事项:
将Semaphore permits的值设置为0,所有acquire()
的调用都将阻塞,直到出现release()
。
如果Semaphore permits
的值> 0,则最好将方法dequeue
修改为返回Option[Int]
,以解决使空队列出队的情况。
如果应用程序中只有一个队列,请考虑将ThreadSafeQueue定义为object ThreadSafeQueue
。
有一种使用AtomicReference进行原子安全的原子更新的有效方法。有关这两种方法之间的差异,请参见此SO link。