Multithreading 你用线做过的最酷的事情是什么?

Multithreading 你用线做过的最酷的事情是什么?,multithreading,Multithreading,我想知道的是,我用线程做过的最有趣的事情之一就是编写一个多线程应用程序来解决迷宫问题 虽然没有什么突破性的东西,但它确实很有趣。我曾经让它们按照我的意愿工作过一次!太酷了 伊恩,介意详细说明一下吗?好吧,你不需要用线程来解决迷宫,除非,当然,迷宫是如此复杂,以至于等待时间变得如此难以忍受,以至于你必须添加状态栏,这样用户就不会感到无聊并认为你的程序挂起了。我想说的是,为了在n核上获得n倍的性能提高,我巧妙地并行了一个使用无锁数据结构的算法处理器。但我从来没有实际的需求,特别是因为我的大多数专业代

我想知道的是,我用线程做过的最有趣的事情之一就是编写一个多线程应用程序来解决迷宫问题


虽然没有什么突破性的东西,但它确实很有趣。

我曾经让它们按照我的意愿工作过一次!太酷了

伊恩,介意详细说明一下吗?好吧,你不需要用线程来解决迷宫,除非,当然,迷宫是如此复杂,以至于等待时间变得如此难以忍受,以至于你必须添加状态栏,这样用户就不会感到无聊并认为你的程序挂起了。

我想说的是,为了在n核上获得n倍的性能提高,我巧妙地并行了一个使用无锁数据结构的算法处理器。但我从来没有实际的需求,特别是因为我的大多数专业代码都是针对单核系统的

几乎每次我在任何语言中使用多个线程时,这都是两个原因之一:

  • 系统(或第三方)提供了一个阻塞API,我需要一个异步API(或者至少让多个操作同时运行)
  • 利用基于优先级的先发制人调度,让一切都保持良好的响应性,而不必手动将所有缓慢的操作切成小块
这是必要的,但不是你所说的迷人的。哦,它们不是复杂的迷宫

迷宫是在一个数组中定义的,与此类似:

String[] MazeArray = new String[5];

MazeArray[0] = "---X---X-------XF";
MazeArray[0] = "-X-X-X---XXXXXXX-";
MazeArray[0] = "-X-X-X-X-X---X---";
MazeArray[0] = "-X-X-X-XXX-X-X-X-";
MazeArray[0] = "SX---X-----X---X-";
当路径中有分支时,我会生成一个新的工作线程,并让该线程研究该路径。然后,通过一些基本逻辑,我可以确定最短路径、最长路径等

所列的例子显然过于简化,但它应该说明这一点。这是一项有趣的运动,如果你有几分钟的空闲时间,你应该试试


伊恩

我不知道这是否算数,但对我来说,一个能工作的多线程软件本身就很吸引人,而不是它们所达到的目的。在您的程序中,大约有10、20、100名工作人员使用相同的基础结构(单例、文件等)。让一切与互斥体、信号量、上下文切换等协调工作是一件很好的事情,就像作为一名管理者和您的团队完美地合作一样。您阅读了应用程序日志,看到线程为了一个共同的目标而协作,这非常棒。有人能体会到这种感觉吗?

这真的很普通,但它是迈向更具创造性的线程的一个很好的垫脚石:


在上载新数据并为我处理它的类型请求中,请求线程接受数据并将其放入队列中,用户继续他们的快乐之路。一个或多个后台线程不断地排在队列中并以某种方式处理它们。

我对线程没用,我得让我的女朋友重新整理我的按钮。< /P> < P>我在C++中编写了一个小的FCGI servlet模型,它为每个新的请求分配了一个新的线程。p> 如果你不认为这很酷,你应该看看当我通过它抽3K请求/秒时发生了什么。我不小心忘了清理它们,即使是你,它们都自动终止并停止实际使用内存,它们仍然消耗寻址,我让应用程序快速重新保存了比我更多的内存,并停止创建线程

(当时我使用的是32位,在创建了2^32个线程后,它实际上停止了。天知道64位会做什么)

此外,我还为著名的命令
rm-rf
创建了一个多线程(嗯,forking)广度优先的目录上fork替换。主要是rm-rf似乎在等待IO以yay/nay响应,这使得它在某些目录结构(如squid缓存)上的速度变慢,这让我感到沮丧。这段代码唯一真正需要注意的是,它只具有娱乐价值,如果在整个文件系统上使用,这将是两种场景之间的竞争:

  • 磁盘被擦除,使其无法使用,并可能擦除允许您告诉它死亡的命令
  • 该系统“叉式轰炸”的原因是叉式轰炸速度太快,操作强度太高,甚至无法响应命令
    在“fork bombling”的情况下,巨大的生成率可能导致递归rm停止自身(或者命中Ulimit,如果有的话)

    我们曾经编写了一个多线程应用程序,它基本上逐行读取文件,并在内部数据库中查找是否有匹配项,附加一些数据并移动到下一行。但其复杂性在于,可以同时处理多个文件,并且可以搜索每个文件的多个记录。有一个管理器类,它知道有多少线程可用,并负责将可用的工作线程划分到每个文件(如果只有一个要处理的文件,它将接收全部40个线程,如果有5个文件,根据优先级,每个文件将接收这40个线程的一小部分)。我们最初使用异步委托,但注意到很难捕获异步线程中可能发生的任何异常,因此我们使用.net中的传统线程启动

    关键是在manager类中有一个ManualResetEvents集合,该集合由ManualResetEvents组成,ManualResetEvents是worker类(线程)中的公共属性。当工作线程将完成时,它将发出ManualResetEvent的信号,该事件将由Manager类上的.WaitAny()拾取。然后,管理器将知道其中一个线程已完成,并将启动一个新线程。事实上,它比这稍微复杂一点,但这是它所做的核心

    最困难的部分是单元测试,以确保在任何给定的时间运行正确数量的线程。我们进行了一些测试,这些测试的作用就像队列中只有一个文件(获取所有40个线程),然后引入了另一个文件,线程的分配必须循环到每段20个文件。我们哈
    new Thread(() => 
    {
        // do stuff in a new thread's context
    })
    {
        Name = "Thread " + GetHashCode().ToString(),
        Priority = this.threadPriority
    }
    .Start();