C# 代码理解问题
今天早上我在读一段源代码时,遇到了一个我不理解的C代码示例:C# 代码理解问题,c#,C#,今天早上我在读一段源代码时,遇到了一个我不理解的C代码示例: public bool Dequeue(out T value) { Node head; Node tail; Node next; while (true) { // read head head = this.head; tail = this.tail; next = head.Next; // Are
public bool Dequeue(out T value)
{
Node head;
Node tail;
Node next;
while (true)
{
// read head
head = this.head;
tail = this.tail;
next = head.Next;
// Are head, tail, and next consistent?
if (Object.ReferenceEquals(this.head, head))
{
// Source code continues here...
}
// And here...
}
}
我遇到了一个问题,它包含Object.ReferenceEquals()
如果我理解得很好,源代码作者想比较
this.head
和head
,但在上面几行中,他只写了head=this.head
这句话主要来自C++
的背景,对我来说毫无意义。此外,在某些情况下,Object.ReferenceEquals()
行似乎抛出了一个System.NullReferenceException
,所以它肯定会做些什么,我就是不知道是什么
你能帮我理解这条线的作用和可能的原因吗
如果需要,这里是节点
类定义(我猜它是一个“模板”类,不确定C#的措辞):
多谢各位
编辑:该方法的其余部分,供询问者使用
public void排队(T值)
{
//从空闲列表中分配一个新节点
节点值节点=新节点(值);
while(true)
{
Node tail=this.tail;
Node next=tail.next;
//尾巴和下一个一致吗
if(Object.ReferenceEquals(tail,this.tail))
{
//尾部是否指向最后一个节点?
if(Object.ReferenceEquals(next,null))
{
如果(Object.ReferenceEquals(
联锁比较交换(参考tail.Next,valueNode,Next),
下一个
)
)
{
联锁。比较交换(参考this.tail、valueNode、tail);
打破
}
}
else//tail未指向最后一个节点
{
//尝试将尾部摆动到下一个节点
联锁。比较交换(参考this.tail,next,tail);
}
}
}
}
如果this.head
和this.tail
是公共的,则可以在循环运行时更改它们Object.ReferenceEquals
检查它们是否与方法执行时相同
如果没有整个课堂/上下文,很难给出更完整的答案
他刚刚写了这个
这是一项作业,与比较它们无关。注意,这是关于一个字段head
和一个本地变量this.head
if(Object.ReferenceEquals(this.head,head))
在这里,作者希望比较
this.head
和head
,同时确保相等是基于它们的引用(地址),而不是基于=
和Equals()的任何(可能)重载
我假设本地varhead
在循环中被更改,这使得它成为一个有争议的命名 ReferenceEquals是一个函数,用于确保一个对象的两个实例是完全相同的对象,而不仅仅是两个具有相同值的对象。文档可在此处找到()。至于该语句的目标,如果这段代码是在多线程上下文中执行的,那么他可能会试图确保没有人弄乱了head(非常危险),或者担心有人传入了值类型(危险,但更好的检查方法)
编辑:随着进一步的代码发布,它看起来像是第一件事。他使用ReferenceEquals试图在有多个线程的情况下捕捉竞争条件(如果不是多线程的,他就不会使用InterlocatedExchange)。代码似乎基本上是在尝试执行一个操作,如果有人在中途对其进行了更改,只需再次尝试(while(true))。使用关键部分或信号量来确保没有人修改您的值可能更为优雅,而不是简单地希望您可以检查它们是否修改了。原因是,在IF之后,但在InterlocatedExchange之前,可能会有人修改您的值,这会引入错误 看起来像一个链表。出列看起来像一个递归函数。
所以,要么“下一步”对节点的“头部”部分执行操作,要么它并行运行,在继续之前,他试图检查内容是否仍在原来的位置。最后一部分做得不正确,因为在进入关键部分时应该使用信号量,否则您将遇到竞争条件,它迟早会失败 该方法用于执行线程安全比较和替换-这意味着该方法应该能够处理队列被外部线程修改的情况。
if
语句试图处理列表被其他线程修改的情况在哪个类中是Dequeue
方法所在的对象。ReferenceEquals()
永远不会抛出NullReferenceException
是否确定异常发生在该位置?是否可以发布该方法的其余部分?这可能会把事情弄清楚。另外,你知道这段代码工作正常吗?@Ophir Yoktan:Done。至少9个月以来,该代码似乎运行良好。然而,从一段时间以来,前面提到的行抛出了一个NullReferenceException
(我猜是网络问题,我们经常遇到一些问题)@jdehaan:是的。除非堆栈跟踪不可靠?(可能是,我不知道)我认为这句话的主旨是,如果你把一个赋值给另一个,一个ReferenceEquals调用来检查它们是否等同于检查编译器,或者一个穷人的线程安全工具。我认为他遗漏的一点是,这是C#中的一个引用赋值。给C++程序员<代码>节点头;<鳕鱼
private class Node
{
public T Value;
public Node Next;
public Node(T value)
{
this.Value = value;
}
}
public void Enqueue(T value)
{
// Allocate a new node from the free list
Node valueNode = new Node(value);
while (true)
{
Node tail = this.tail;
Node next = tail.Next;
// are tail and next consistent
if (Object.ReferenceEquals(tail, this.tail))
{
// was tail pointing to the last node?
if (Object.ReferenceEquals(next, null))
{
if (Object.ReferenceEquals(
Interlocked.CompareExchange(ref tail.Next, valueNode, next),
next
)
)
{
Interlocked.CompareExchange(ref this.tail, valueNode, tail);
break;
}
}
else // tail was not pointing to last node
{
// try to swing Tail to the next node
Interlocked.CompareExchange<Node>(ref this.tail, next, tail);
}
}
}
}