java.util.Stack或java.util.Queue存在什么线程安全问题
如果我忽略size()的不精确性,并假设我分配了足够大的底层向量,这样就不会发生重新分配,那么java.util.Stack或java.util.Queue有什么线程安全问题 我想不出一个有效/合理的一致性论点来说它们是线程不安全的 有人有一些见解吗?,它扩展了,使每个方法都同步。这意味着与单个方法的交互是线程安全的 是一个接口。跨线程使用的安全性取决于各个实现。例如,一个是线程安全的,但一个不是线程安全的。,它扩展了,使每个方法都同步。这意味着与单个方法的交互是线程安全的 是一个接口。跨线程使用的安全性取决于各个实现。例如,a是线程安全的,但a不是。“线程安全”不是类的绝对属性——安全或不安全的是您对对象的使用。您可以想出不安全的方法来使用java.util.Stack或java.util.Queue存在什么线程安全问题,java,Java,如果我忽略size()的不精确性,并假设我分配了足够大的底层向量,这样就不会发生重新分配,那么java.util.Stack或java.util.Queue有什么线程安全问题 我想不出一个有效/合理的一致性论点来说它们是线程不安全的 有人有一些见解吗?,它扩展了,使每个方法都同步。这意味着与单个方法的交互是线程安全的 是一个接口。跨线程使用的安全性取决于各个实现。例如,一个是线程安全的,但一个不是线程安全的。,它扩展了,使每个方法都同步。这意味着与单个方法的交互是线程安全的 是一个接口。跨线程使
ConcurrentHashMap
,也可以想出线程安全的方法来使用普通的HashMap
当人们说一个类是线程安全的时,通常意味着每个方法都是以线程安全的方式实现的。从这个意义上说,堆栈
是线程安全的。但是它的接口不允许轻松/安全地处理常见用例,因此从这个意义上讲,它不是非常线程安全的
例如,如果您的代码检查堆栈
是否为空,如果为空,则弹出一个元素——这是不安全的,因为它可能有一个元素(因此不是空的),但其他人在您有机会弹出它之前弹出了它(在这种情况下,您尝试弹出一个空堆栈,并将得到一个异常)
为了更线程安全,您确实需要一个方法来处理这种情况。A给了你这个。例如,take()
将阻塞直到有一个值要弹出,而poll()
将立即返回一个值或null
(如果没有要弹出的元素)。“线程安全”不是类的绝对属性——安全或不安全的是您对对象的使用。您可以想出不安全的方法来使用ConcurrentHashMap
,也可以想出线程安全的方法来使用普通的HashMap
当人们说一个类是线程安全的时,通常意味着每个方法都是以线程安全的方式实现的。从这个意义上说,堆栈
是线程安全的。但是它的接口不允许轻松/安全地处理常见用例,因此从这个意义上讲,它不是非常线程安全的
例如,如果您的代码检查堆栈
是否为空,如果为空,则弹出一个元素——这是不安全的,因为它可能有一个元素(因此不是空的),但其他人在您有机会弹出它之前弹出了它(在这种情况下,您尝试弹出一个空堆栈,并将得到一个异常)
为了更线程安全,您确实需要一个方法来处理这种情况。A给了你这个。例如,
take()
将阻塞直到有一个值要弹出,而poll()
将立即返回一个值或null
(如果没有要弹出的元素)。从ArrayBlockingQueue查看此方法(将任何现有同步放在一边):
让线程A前进到这里,让线程B接管并执行该方法;那么让我们继续。很容易看出,B的ex
覆盖A的ex
,计数增加2,putIndex提前两次
类似的情况也可以在其他方法中找到
所有带有数据内存和记账变量的数据结构都很容易受到非同步并发访问的影响。从ArrayBlockingQueue查看此方法(将任何现有同步放在一边): 让线程A前进到这里,让线程B接管并执行该方法;那么让我们继续。很容易看出,B的
ex
覆盖A的ex
,计数增加2,putIndex提前两次
类似的情况也可以在其他方法中找到
所有具有数据内存和簿记变量的数据结构都很容易受到非同步并发访问的攻击。如果同时弹出和弹出,会怎么样?如果同时弹出、推送和弹出,会怎么样P@alfasin你应该同时使用
push
和push
来做什么。你们能定义一下应该发生什么吗?@QiangLi如果我在不同的线程中同时推两个值,那么其中一个可能会被擦除(有时称为幻影写入)。如果我在不同的线程中同时弹出两个值,那么我可能会得到两次相同的值(这有时称为幻象读取)。如果读和写同时发生(有时称为脏读或脏写),则可能会发生其他类型的问题。如果同时弹出和弹出怎么办?如果同时弹出、推和弹出怎么办P@alfasin你应该同时使用push
和push
来做什么。你们能定义一下应该发生什么吗?@QiangLi如果我在不同的线程中同时推两个值,那么其中一个可能会被擦除(有时称为幻影写入)。如果我在不同的线程中同时弹出两个值,那么我可能会得到两次相同的值(这有时称为幻象读取)。如果读和写同时发生(有时称为脏读或脏写),则可能会发生其他类型的问题。是的,我应该提到“队列”是一个接口。当使用LinkedList
或Deque
时,为什么它们不是线程安全的?LinkedList上的文档非常清楚“如果多个线程同时访问一个链接列表,并且至少有一个线程
private void insert(E x) {
items[putIndex] = x;
// HERE
putIndex = inc(putIndex);
++count;
notEmpty.signal();
}