【问题标题】:Multithreaded access to singleton class多线程访问单例类
【发布时间】:2014-11-19 22:16:16
【问题描述】:

我很难集中精力访问具有多个线程的单例类。

这篇文章为我提供了一个很好的起点来确保我的单例线程安全:http://csharpindepth.com/Articles/General/Singleton.aspx

我的单例类应该将一组文件视为一个单一的数据单元,但以并行方式处理它们。

我将每个文件的信息存储在字典中,并向调用线程返回一个唯一键(将使用 DateTime 和随机数创建),以便每个线程稍后可以引用自己的文件。

public string AddFileForProcessing(FileForProcessing file)
{
    var id = CreateUniqueFileId();
    var resultFile = CreateResultFileFor(file);
    //These collections are written here and only read elsewhere
    _files.Add(id, file); 
    _results.Add(id, resultFile)
    return id;
}

然后后面的线程调用传递这个 id 的方法。

public void WriteProcessResultToProperFile(string id, string[] processingResult)
{
   //locate the proper file in dictionary using id and then write information...
    File.AppendAllLines(_results[key].FileName, processingResult);
}

这些方法将在一个类中被访问:

a) 响应 FileWatcher 的 Created 事件并创建调用 AddFileForProcessing 的线程:

public void ProcessIncomingFile(object sender, EventArgs e)
{
    var file = ((FileProcessingEventArg)e).File;
    ThreadPool.QueueUserWorkItem(
    item =>
    {
        ProcessFile(file);
    });
}

b) 在 ProcessFile 中,我将文件添加到字典并开始处理。

private void ProcessFile(FileForProcessing file)
{
    var key = filesManager.AddFileForProcessing(file);
    var records = filesManager.GetRecordsCollection(key);

    for (var i = 0; i < records.Count; i++)
    {
        //Do my processing here
        filesManager.WriteProcessResultToProperFile(key, processingResult);
    }
}

现在我不明白当两个线程调用这些方法时会发生什么,因为它们都使用同一个实例。

每个线程都会使用不同的参数调用 AddFileForProcessing 和 WriteProcessResultToProperFile。这是否使他们成为两个不同的电话?

由于它将对一个文件进行操作,该文件将由属于单个线程的 id 唯一标识(即,没有文件会遭受多次访问),我可以保留这个方法还是我仍然必须“锁定”我的方法?

【问题讨论】:

  • 这个方法使用的实例数据是什么?
  • 如果_files 不是一个安全的集合,你将不得不在它周围使用锁定。
  • 关键是,您如何确保“每个线程都会使用 不同的 参数进行调用”。 1._files是由单线程还是多线程填充? 2. _files 是否只在before 线程被启动? 3.如何确保每个处理线程从_files中选择一个唯一的id。您能否也分享所有这 3 个场景?
  • “我将每个文件的信息存储在字典中,并返回给调用线程一个唯一的键,以便每个线程以后可以引用自己的文件。”在单例类实例所在线程的初始化过程中?
  • 换句话说..文件的集合会在运行时改变吗?

标签: c# multithreading singleton


【解决方案1】:

是的,只要您只从共享字典中阅读,一切都应该没问题。正如您正确提到的,只要它们是不同的文件,您就可以并行处理这些文件。

The documentation 解释:

只要不修改集合,Dictionary&lt;TKey, TValue&gt; 可以同时支持多个读取器。

所以,如果有人可以调用AddFileForProcessing(没有锁),你就不能并行做任何事情。但是只要打电话给WriteProcessResultToProperFile,就可以了。这意味着,如果您想并行调用AddFileForProcessing,那么您需要在both 方法中加锁(实际上:所有将触及该字典的代码部分)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多