1
public void Remove(T item)
{
    locker.EnterWriteLock();        
    try
    {
        list.Remove(item);
    }
}

以上是实例类的方法。说实例是myObject. 关于上面的片段,我的问题是:

线程一调用myObject.Remove(A)
线程一执行locker.EnterWriteLock()

线程两个调用myObject.Remove(B)

线程一进入 try 块并执行list.Remove()

此时的价值是item多少?ielist.Remove()会以 A 或 B 作为参数调用吗?

4

6 回答 6

4

每个线程都有自己的调用堆栈,方法参数存储在该堆栈中。堆栈不在线程之间共享。

在线程一个的堆栈中,有一行指示Remove正在被调用,并且包含“A”或对“A”的引用(取决于它是值还是引用类型)。

当线程二进入该方法时,它有自己的调用堆栈(线程 1 的堆栈在线程二运行时未使用),其中有一行指示Remove项目“B”的开始。然后该线程被挂起,它的调用堆栈未被使用,我们回到线程 1,其中项目“A”是调用堆栈上的内容。

在将来的某个时候,线程二将被重新激活,并且在它的调用堆栈上将有项目“B”。

于 2013-01-08T22:56:00.620 回答
1

方法参数分配在调用该方法的线程的堆栈上。因此,每个线程都有自己的论点,它们不会相互影响。

于 2013-01-08T22:55:42.940 回答
0

我怀疑你应该在这里锁定的是list变量。您正在调用它的Remove方法,并且如果此list变量是某种不是线程安全的类型,List<T>例如,如果从同一实例上的多个线程同时调用此方法myObject(这是您的list字段所在的位置) ,您可能会遇到麻烦. 就方法的论点而言,很难在方法的上下文中谈论它们的任何线程安全性。

于 2013-01-08T22:52:31.140 回答
0

.Net 不提供对参数的任何继承锁定。但是,list.Remove(item)不修改item(假设它是标准System.Collections或实现)并且使用不同的参数两次调用相同的方法会创建(每个方法调用中System.Collections.Generic的一个)的两个副本,而不是一个。item

相反,我会锁定列表,因为大多数类的实例方法不能保证是线程安全的。

于 2013-01-08T22:55:05.850 回答
0

线程 2 将等待locker.EnterWriteLock();线程 1 执行locker.ExitWriteLock();

list所以线程 2在线程 1 调用之前无法访问locker.ExitWriteLock();

如果您担心参数item,请确保它通过堆栈传递,并且每个线程都有自己的,所以item真的不能被另一个线程“替换”......

所以答案是:如果线程 1locker.EnterWriteLock();在线程 2 之前调用,A将在B.

于 2013-01-08T22:55:17.507 回答
0

的值item将是A参数的值。

只有在该行locker.ExitWriteLock执行后,该块才可用于线程一。

于 2013-01-08T22:56:11.753 回答