我无法理解任何数据结构如何“非阻塞”。
假设您正在制作“非阻塞”哈希表。在某些时候,你的哈希表太满了,所以你必须重新哈希到一个更大的表中。
这意味着您需要分配内存,这是一种全局资源。因此,似乎您必须获取某种锁以防止堆的全局损坏...无论您的数据结构本身可能出现什么问题!
但那意味着在分配内存时,每个其他线程都必须阻塞...
我在这里想念的是什么? (如何)你可以在不阻塞正在做同样的另一个线程的情况下分配内存吗?
答案 0 :(得分:3)
非阻塞设计的两个示例是optimistic design和Transactional Memory。
这个想法是 - 在大多数情况下,阻塞是多余的 - 因为两个OP可以同时发生而不会相互中断。但是,有时当两个OP同时发生并且数据因此而损坏时 - 您可以回滚到之前的状态,然后重试。
这些设计中可能仍然存在锁定,但数据被锁定的时间明显更短,并且仅限于发生OP影响的关键时间。
答案 1 :(得分:2)
仅针对某些定义,其他信息以及区分非阻止,无锁和等待条款,我建议阅读以下文章(我不会在这里复制相关段落,因为它太长了):
答案 2 :(得分:2)
大多数策略都有一个共同的基本模式。他们在循环中使用compare and swap (CAS)操作,直到成功为止。
例如,让我们考虑使用链表实现的堆栈。我选择了一个链表实现,因为很容易与CAS并发,但还有其他方法可以实现。我将使用类似C的伪代码。
Push(T item)
{
Node node = new Node(); // allocate node memory
Node initial;
do
{
initial = head;
node.Value = item;
node.Next = initial;
}
while (CompareAndSwap(head, node, initial) != initial);
}
Pop()
{
Node node;
Node initial;
do
{
initial = head;
node = initial.Next;
}
while (CompareAndSwap(head, node, initial) != initial);
T value = initial.Value;
delete initial; // deallocate node memory
return value;
}
在上面的代码中,CompareAndSwap
是一个非阻塞的原子操作,它用一个新值替换内存地址中的值并返回旧值。如果旧值与预期值不匹配,则旋转循环并再次尝试。
答案 3 :(得分:0)
所有non-blocking意味着你永远不会无限期地等待,而不是你永远不会等待。只要您的堆也使用非阻塞算法实现,您可以在其上实现其他非阻塞算法。