我无法理解任何数据结构如何“非阻塞”。
假设您正在制作一个“非阻塞”哈希表。在某些时候,您的哈希表太满了,因此您必须重新哈希到一个更大的表中。
这意味着您需要分配内存,这是一种全局资源。所以看起来你必须获得某种锁来防止堆的全局损坏......不管你的数据结构本身可能存在的问题!
但这意味着在您分配内存时,所有其他线程都必须阻塞......
我在这里想念什么?
(如何)你能在不阻塞另一个做同样事情的线程的情况下分配内存吗?
我无法理解任何数据结构如何“非阻塞”。
假设您正在制作一个“非阻塞”哈希表。在某些时候,您的哈希表太满了,因此您必须重新哈希到一个更大的表中。
这意味着您需要分配内存,这是一种全局资源。所以看起来你必须获得某种锁来防止堆的全局损坏......不管你的数据结构本身可能存在的问题!
但这意味着在您分配内存时,所有其他线程都必须阻塞......
我在这里想念什么?
(如何)你能在不阻塞另一个做同样事情的线程的情况下分配内存吗?
只是为了一些定义,附加信息以及区分non-blocking,lock-free和wait-free术语,我建议阅读以下文章(我不会在这里复制相关段落,因为它太长了):
大多数策略都有一个共同的基本模式。他们在循环中使用比较和交换 (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
中是一个非阻塞的原子操作,它将内存地址中的值替换为新值并返回旧值。如果旧值与预期值不匹配,那么您将通过循环并再次尝试。
所有这些非阻塞意味着你永远不会无限期地等待,而不是你永远不会等待。只要您的堆也是使用非阻塞算法实现的,您就可以在它之上实现其他非阻塞算法。