繁体   English   中英

试图理解C#中的多线程

Trying to understand multi-threading in C#

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我正在尝试理解多线程的基础知识,所以我构建了一个小程序,提出了一些问题,我会感谢任何帮助:)

这是一个小程序:

class Program
{
    public static int count;
    public static int max;
    static void Main(string[] args)
    {
        int t = 0;
        DateTime Result;
        Console.WriteLine("Enter Max Number : ");
        max = int.Parse(Console.ReadLine());
        Console.WriteLine("Enter Thread Number : ");
        t = int.Parse(Console.ReadLine());

        count = 0;

        Result = DateTime.Now;
        List<Thread> MyThreads = new List<Thread>();
        for (int i = 1; i < 31; i++)
        {
            Thread Temp = new Thread(print);
            Temp.Name = i.ToString();
            MyThreads.Add(Temp);
        }

        foreach (Thread th in MyThreads)
            th.Start();

        while (count < max)
        {
        }

        Console.WriteLine("Finish , Took : " + (DateTime.Now - Result).ToString() + " With : " + t + " Threads.");
        Console.ReadLine();
    }

    public static void print()
    {
        while (count < max)
        {
            Console.WriteLine(Thread.CurrentThread.Name + " - " + count.ToString());
            count++;
        }
    }
}

我通过一些测试运行检查了这个:

我将最大数量设为100,似乎最快的执行时间是2个线程,比10个线程的时间快80%。

问题:

1)线程4-10甚至不打印一次,怎么会这样?

2)不应该更多的线程更快?

我将最大数量设为10000并禁用打印。

使用此配置,5个线程似乎是最快的。

为什么与第一次检查相比有变化?

而且在这种配置中(带打印)所有线程都会打印几次。 为什么与第一次打印不同,只打印了几个线程?

有没有办法让所有线程逐个打印? 在一条线或类似的东西?

非常感谢您的帮助 :)

3 个回复

您的代码肯定是进入线程世界的第一步,您刚刚经历了第一次(很多)头痛!

首先, static可以使您在线程之间共享变量,但它不以线程安全的方式执行。 这意味着你的count < max expression和count++不保证是最新的,或者是线程之间的有效保护。 max仅为10(在我的8处理器工作站上设置为4)时,查看程序的输出:

T0 - 0
T0 - 1
T0 - 2
T0 - 3
T1 - 0 // wait T1 got count = 0 too!
T2 - 1 // and T2 got count = 1 too!
T2 - 6
T2 - 7
T2 - 8
T2 - 9
T0 - 4
T3 - 1 // and T3 got count = 1 too!
T1 - 5

关于每个线程逐个打印的问题,我假设您正在尝试协调对count访问。 您可以使用同步原语(例如C#中的lock语句)来完成此操作。 以下是对代码的简单修改,这将确保仅发生max增量:

static object countLock = new object();

public static void printWithLock()
{
    // loop forever
    while(true)
    {
        // protect access to count using a static object
        // now only 1 thread can use 'count' at a time
        lock (countLock)
        {
            if (count >= max) return;

            Console.WriteLine(Thread.CurrentThread.Name + " - " + count.ToString());
            count++;
        }
    }
}

这个简单的修改使您的程序在逻辑上正确,但也很慢 该示例现在出现了一个新问题: 锁争用 每个线程现在都在争夺对countLock访问countLock 我们已经使程序线程安全,但没有并行性的任何好处!

线程和并行性并不是特别容易实现,但幸运的是.Net的最新版本带有任务并行库(TPL)并行LINQ(PLINQ)

图书馆的美妙之处在于转换当前代码是多么容易:

var sw = new Stopwatch();

sw.Start();
Enumerable.Range(0, max)
          .AsParallel()
          .ForAll(number =>
               Console.WriteLine("T{0}: {1}",
                                 Thread.CurrentThread.ManagedThreadId,
                                 number));

Console.WriteLine("{0} ms elapsed", sw.ElapsedMilliseconds);

// Sample output from max = 10
// 
// T9: 3
// T9: 4
// T9: 5
// T9: 6
// T9: 7
// T9: 8
// T9: 9
// T8: 1
// T7: 2
// T1: 0
// 30 ms elapsed

上面的输出是一个有趣的例子,说明为什么线程会为新用户产生“意外结果”。 当线程并行执行时,它们可以在不同的时间点完成代码块,或者一个线程可能比另一个线程更快。 你永远不会真正了解线程!

您的打印功能远非线程安全,这就是4-10不打印的原因。 所有线程共享相同的max和count变量。

更多线程降低速度的原因可能是每次处理器在每个线程之间改变焦点时发生状态更改。

此外,当您创建大量线程时,系统需要分配新线程。 大多数情况下,现在建议使用Tasks,因为它们是从系统管理的线程池中提取的。 因此不一定必须分配。 创建一个独特的新线程相当昂贵。

无论如何看看这里: http//msdn.microsoft.com/en-us/library/aa645740( VS.71) .aspx

仔细看:

    t = int.Parse(Console.ReadLine());

    count = 0;

    Result = DateTime.Now;
    List<Thread> MyThreads = new List<Thread>();
    for (int i = 1; i < 31; i++)
    {
        Thread Temp = new Thread(print);
        Temp.Name = i.ToString();
        MyThreads.Add(Temp);
    }

我想你错过了变量t (i <31)。

在编写代码之前,您应该阅读许多关于并行和多线程编程的书籍,因为编程语言只是一种工具。 祝好运!

1 理解多线程C#

我想了解多线程。 我有一个示例在控制台应用程序中运行Main方法的两个线程。 发生的事情是,我的控制台是黑色的,没有写在上面,但是当我按任意键时它会显示正确的结果。 为什么? ...

2 帮助理解C#和多线程

嗨,我正在阅读“C#中的线程化”教程。 它提到的一件事是: “CLR为每个线程分配自己的内存堆栈,以便局部变量保持独立” 还有这个例子: } 输出:1 2 2 4 6 8 10 10 10 10 12 12 14 15 17 18 18 20 20 所以我理解这 ...

3 C#中的多线程

我试图从书中运行以下程序。 作者声称结果输出“应该” 1000 2000 .... 10000 如果您在普通处理器上运行该程序,但在多处理器计算机上运行它可能是 999 1998年 ... 9998 当使用正常增量方法(数字+ = ...

2010-11-04 03:26:37 3 269   c#
4 c#中的多线程

我是新来的线程。 我的老板给了我一个方案。我们有一个对象列表,它是0f 70gb,我们要从数据库中加载它。在这种情况下,我想花点时间来利用cpu(多线程)。 ,而不是第二部分,当第二部分加载时意味着在处理第一部分时,我应该做的就是指导我。 ...

5 试图理解C#中的异常

我在代码中并没有真正使用任何try / catches,但我试图打破这种习惯,现在开始使用异常。 我认为在我的应用程序中最重要的地方是读取文件,我现在正在尝试实现它,但我不确定这样做的“最佳实践”。 目前我正在做这样的事情: 但我不确定这是否正确。 我有这个来处理它: ...

6 C#。 多线程

我有两个线程。 他们中的第一种实现了两种方法,第二种仅实现了一种。 我需要这样同步线程:从第一个线程执行第一个方法,从第二个线程执行方法,从第一个线程执行第二个方法。 我尝试使用障碍物,但无济于事: 我该如何解决? 非常感谢你! 感谢您的所有帖子。 我尝试使用barr ...

7 C#多线程

好的。 我想运行两个线程。 当前代码: 两者都在访问同一个List,问题是我猜第一个线程“ foo”没有释放锁。 因为“ bar”仅在“ foo”完成时开始。 谢谢 ...

9 C#多线程

我得到了一个打印服务,该服务现在也将进行文件集成,以便同时完成关于使用线程的两项任务。 看完该线程教程后,我接着搜索了Join的功能。 如果我没看错,Join会终止线程,对吗? 所以我在这里的问题是,由于该服务应该在一天24/7之前运行,直到有人需要停止线程,我是否可以仅执行Thr ...

10 C#多线程

让我说我有一个事件,每个秒被解雇10次 我想要方法DoLongOperation(e); 每次事件被触发时在一个单独的线程上处理, 我可以这样做: 但我觉得这对性能不好,我想达到最佳性能,那么我能做的最好的事情是什么? 谢谢你... 编辑:当我说多长时间我并不 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM