有关多线程的基本问题

时间:2020-03-18 17:54:02

标签: c# multithreading tcp

我很好奇这是否允许语法,以及它到底是做什么的

public void startThreads(string userIp){
     user1 = new TCPListener("0.0.0.0", 1111);
     tmpThread = new Thread(new ThreadStart(() => User1Listern(user1);
     tmpThread.Start();

     user2 = new TCPListener("0.0.0.0", 1112);
     tmpThread = new Thread(new ThreadStart(() => User2Listern(user2);
     tmpThread.Start();

     user3 = new TCPListener("0.0.0.0", 1113);
     tmpThread = new Thread(new ThreadStart(() => User3Listern(user3);
     tmpThread.Start();
}

public void User3Listern(TCPListener tmp){
    tcpLister = (TCPListener)tmp;
    user3.Start(); //Start User3 
    Thread.Sleep(1000);
    //MS documenation
    while(true){
        user3 = this.tcpListener.AccepTcpClient();
        Thread User3Start = new Thread(new ParamertizedThreadStart(User3Profile));
        User3Start.Start(user3);
    }    
}

我的问题:

  • 一个线程可以包含多个这样的线程吗? (tmpThread)
  • 如果您不“加入”这些内容,而只是“启动”它们会发生什么。

2 个答案:

答案 0 :(得分:2)

一个线程可以包含多个这样的线程吗?

这不是正在发生的事情。这些线程不会以任何方式“连接”。每次都创建和启动一个。

执行此操作时:

tmpThread = new Thread(new ThreadStart(() => User2Listern(user2);

新线程与上一个线程无关。此处发生的事情甚至与线程实际上没有任何关系,对于任何对象也是如此。

正在创建一个新对象,并且变量现在指向该新对象,而不是旧对象。旧的仍然存在。如果没有任何东西在使用旧对象,那么它可能可以在后台进行垃圾收集。但是这里不是这种情况,旧对象仍在内存中,并且仍作为线程执行其工作。 变量现在仅指向一个新对象。

如果在此方法结束时检查tmpThread的内容,则会发现它仅引用最后创建的Thread对象。该方法不再引用前两个对象。

答案 1 :(得分:1)

让我从您跳过的几个基本概念开始:

  • 您发布的代码已被当前C#.Net标准淘汰,不再使用您发布的Thread API,到目前为止,所有操作都使用Parallel API完成,该API内部使用{{1 }}

什么是线程?

  • Windows是多线程操作系统,与Linux是多进程操作系统不同,线程通常只是简单的一组执行指令。
  • 在多核系统上,每个核可以执行多个这样的指令,因此可以有多个线程/进程。
  • 因此,线程不过是逻辑单元和轻量级执行上下文
  • 现在Windows中的每个进程都有一个Main线程,并且还具有在后台执行其他任务(后台线程或线程池线程)的能力,从而可以在后台执行其他任务,这具有多种用途,例如使处理更快(并行-CPU)。 / IO绑定)
  • 主线程是前台线程,池线程始终是后台线程。没有主线程/前台线程就不能存在后台线程,因为执行它的进程将与主线程一起消失。

现在您的代码及其用途了吗?

  • 您将启动三个后台线程,在此处您将根据构造函数的要求提供委托。
  • 对于第三个线程,您可能正在每个线程上传递TCPListener来侦听传入的TCP请求。
  • 所有线程均在主线程上启动,并在后台开始执行

我的问题是一个线程可以包含多个这样的线程吗? (tmpThread)?

  • 正如我已经澄清的那样,这不是一个包含多个线程的线程,而只是在调用Threadpool方法时执行了后台线程,当由主线程召集然后控制权返回到主线程时,而后台线程在后台完成其任务。

如果您不“加入”这些内容,而只是“启动”它们会发生什么。

  • start指示主线程在退出之前等待背景线程完成,如果未调用join,则主线程可能退出,如果没有什么可处理的,则该过程将完成然后后台线程就像僵尸一样,无法通过它们获得结果。尽管大多数情况下都是这样,如果后台线程正在执行一些内存中的作业,但让我们假设它进行了一次数据库调用,那么这将会成功,但是如果没有预期的结果不会返回,因为没有线程可以接收它们

更多信息

  • 看看您的Thread3代码,那里有无限循环,它可能使系统不堪重负,请记住线程是昂贵的资源
  • 通过Parallel API使用线程池可以实现更好的优化,它永远不会过度配置,不会使系统不堪重负
  • 多线程唯一的问题是竞争条件和死锁,对于它们,各种同步上下文(如锁,信号量)可用
  • 对于多线程设计,并发集合是一个更好的选择

编辑1

回顾fiddle上的TCP服务器实现,我使用了以下link中的引用。

该实现包含什么:

  1. 实现了异步TCP服务器,该服务器在后台等待接收I / p
  2. 一旦收到输入,将对其进行处理,如方法Join
  3. 所示
  4. 由于实现是异步的,您可以启动1000台TCP服务器,而不会对系统造成任何影响,因为没有后台线程阻塞
  5. 主线程将等待后台进程完成
  6. 每个服务器应从唯一的端口启动