【问题标题】:Will parameter of a static object's non-static method be shared from multiple threads?静态对象的非静态方法的参数会被多个线程共享吗?
【发布时间】:2012-09-08 00:43:39
【问题描述】:

(为简洁起见,以下所有内容均已简化)

我有一个对处理对象的静态引用。

处理器包含一个函数,我可以向它传递一个对象包,这是要处理的信息。

包来自应处理的大量包的列表。这些包是独一无二的;这里没有对同一个对象的多个引用。

我启动了许多线程,以便可以并行处理 toProcess 中的包。线程 Pop() 从 toProcess 堆栈中获取一个可用的 Package,直到堆栈为空。

我现在的问题是:我能否冒着Check 中的package 被另一个线程覆盖的风险,或者另一个线程会“创建”Check 的副本?

static class Program
{
    static Processor processor = new Processor();
    static Stack<Package> toProcess;
    static Object sync = new Object();

    static void RunThreads()
    {
        toProcess = GetPackages();
        //start many threads using the Work delegate
    }

    static void Work()
    {
        while(true)
        {
            Package p;
            lock(sync)
            {
                if(toProcess.Count == 0)
                   break;
                p = toProcess.Pop();
            }
            processor.Check(p);
        }
    }
}

class Processor
{
    public void Check(Package package)
    {
        //do many analyses on p and report results of p's analysis to elsewhere
    }
}

class Package
{
    //properties
}

【问题讨论】:

    标签: c# multithreading


    【解决方案1】:

    我现在的问题是:我是否可以冒险检查 Check 中的包被另一个线程覆盖,或者另一个线程会“创建”Check 的副本?

    您的意思不是很清楚,但是对Check 的每个独立调用都会有自己的package 变量。该变量不仅是该线程的本地变量,而且是 Check 的调用(因此递归调用也不会更改它)。

    现在,如果您在多个不同的线程中将相同的Package 引用传递给Check,那么是的,它们都将处理同一个对象,这可能会导致问题。但是package 变量它们自己在不同的调用中是独立的。

    【讨论】:

    • 这回答了我的疑惑。我应该澄清一下 toProcess 堆栈中的所有 Package 引用都指向不同的对象(即 toProcess 中的所有引用都是唯一的,并且没有在其他地方修改)。我的疑问是Check 中的package 参数本身是否独立于来自多个线程的调用。
    【解决方案2】:

    如果Package 是class,即引用类型,并且如果在Check 中执行一些写操作,是的 - 你将必须使用锁定机制来管理对它的访问.

    另一方面:如果Package 是值类型,它将被传递给函数按值。如果Check 只读取信息(即使Package 是引用类型),则无需担心锁定。

    【讨论】:

    • 当它是静态方法的局部变量时,另一个线程如何破坏包?每次都会创建新包。
    • @petro.sidlovskyy:它不是局部变量,它是 Stack<..> 的一部分,它是 静态全局 变量。并且线程运行 Work(..) 函数..
    • 是的,但是 Pop 会将其从堆栈中删除,并且到目前为止,此操作已被锁定,没有其他线程可以访问它。
    • @Tigran:嗯,package 是 Check 方法的局部变量。它是一个参数,它的值不受其他线程的影响。 值所指的对象内的数据可以更改,但这不是一回事。
    • @petro.sidlovskyy:是的,但是 p 对象引用可以指向在另一个线程中更改的完全相同的 p 对象。我说清楚了吗?
    【解决方案3】:

    由于您保证堆栈中的包不能从多个线程中弹出,因此只要堆栈中的包都不相同,就应该没有问题。

    但是,如果 Check 方法改变了 Processor 的状态,您应该在 Check 方法中执行锁定。

    【讨论】:

      猜你喜欢
      • 2011-09-07
      • 1970-01-01
      • 1970-01-01
      • 2014-11-30
      • 1970-01-01
      • 2013-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多