为什么套接字使用线程? [英] Why is threading used for sockets?

查看:40
本文介绍了为什么套接字使用线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

自从我发现套接字以来,我一直在使用非阻塞变体,因为我不想费心学习线程.从那以后,我在线程方面积累了更多的经验,我开始问自己.. 你为什么要将它用于套接字?

Ever since I discovered sockets, I've been using the nonblocking variants, since I didn't want to bother with learning about threading. Since then I've gathered a lot more experience with threading, and I'm starting to ask myself.. Why would you ever use it for sockets?

线程处理的一个重要前提似乎是它们只有在处理自己的数据集时才有意义.一旦有两个线程处理同一组数据,就会出现以下情况:

A big premise of threading seems to be that they only make sense if they get to work on their own set of data. Once you have two threads working on the same set of data, you will have situations such as:

if(!hashmap.hasKey("bar"))
{
  dostuff               // <-- meanwhile another thread inserts "bar" into hashmap
  hashmap[bar] = "foo"; // <-- our premise that the key didn't exist
                        //     (likely to avoid overwriting something) is now invalid
}

现在想象一下 hashmap 将远程 IP 映射到密码.你可以看到我要去哪里.我的意思是,当然,这种线程交互出错的可能性非常小,但它仍然存在,为了保证程序的安全,你必须考虑到每一种可能性.与简单的单线程工作流相比,这将显着增加设计工作量.

Now imagine hashmap to map remote IPs to passwords. You can see where I'm going. I mean, sure, the likelihood of such thread-interaction going wrong is pretty small, but it's still existent, and to keep one's program secure, you have to account for every eventuality. This will significantly increase the effort going into design, as compared to simple, single-threaded workflow.

我完全可以看到线程对于处理单独的数据集或显式优化以使用线程的程序是多么棒.但是对于一般"情况,程序员只关心交付一个工作和安全的程序,我找不到任何理由使用线程而不是轮询.

I can completely see how threading is great for working on separate sets of data, or for programs that are explicitly optimized to use threading. But for the "general" case, where the programmer is only concerned with shipping a working and secure program, I can not find any reason to use threading over polling.

但是看到单独线程"方法非常普遍,也许我忽略了一些东西.开导我!:)

But seeing as the "separate thread" approach is extremely widespread, maybe I'm overlooking something. Enlighten me! :)

推荐答案

使用带有套接字的线程有两个常见原因,一个好,一个不太好:

There are two common reasons for using threads with sockets, one good and one not-so-good:

理由很充分:因为您的计算机有多个 CPU 内核,并且您想利用额外的内核.单线程程序只能使用一个内核,因此在工作负载繁重的情况下,您会将一个内核固定在 100% 的位置,而其他内核则闲置并浪费掉.

The good reason: Because your computer has more than one CPU core, and you want to make use of the additional cores. A single-threaded program can only use a single core, so with a heavy workload you'd have one core pinned at 100%, and the other cores sitting unused and going to waste.

不太好的理由:您想使用阻塞 I/O 来简化程序的逻辑——特别是,您想避免处理部分读取和部分写入,并将每个套接字的上下文/状态保持在与其关联的线程的堆栈.但是您还希望能够同时处理多个客户端,而不会因为慢客户端 A 导致 I/O 调用阻塞和延迟处理快速客户端 B.

The not-so-good reason: You want to use blocking I/O to simplify your program's logic -- in particular, you want to avoid dealing with partial reads and partial writes, and keep each socket's context/state on the stack of the thread it's associated with. But you also want to be able to handle multiple clients at once, without slow client A causing an I/O call to block and hold off the handling of fast client B.

第二个不太好的原因是,虽然每个套接字有一个线程似乎简化了程序的设计,但实际上它通常会使程序复杂化.它引入了竞争条件和死锁的可能性,并使安全访问共享数据变得困难(如您所述).更糟糕的是,如果你坚持阻塞 I/O,那么干净地关闭程序变得非常困难(或者以任何其他方式从线程的套接字以外的任何地方影响线程的行为),因为线程通常被阻塞在 I/O call(可能是无限期的),没有可靠的方法来唤醒它.(信号在多线程程序中不能可靠地工作,回到非阻塞 I/O 意味着你失去了你希望的简化程序结构)

The reason the second reason is not-so-good is that while having one thread per socket seems to simplify the program's design, in practice it usually complicates it. It introduces the possibility of race conditions and deadlocks, and makes it difficult to safely access shared data (as you mentioned). Worse, if you stick with blocking I/O, it becomes very difficult to shut the program down cleanly (or in any other way effect a thread's behavior from anywhere other than the thread's socket), because the thread is typically blocked in an I/O call (possibly indefinitely) with no reliable way to wake it up. (Signals don't work reliably in multithreaded programs, and going back to non-blocking I/O means you lose the simplified program structure you were hoping for)

简而言之,我同意 cib —— 多线程服务器可能有问题,因此通常应该避免,除非你绝对需要使用多核 —— 即便如此,使用多进程而不是多线程可能更好,为了安全起见.

In short, I agree with cib -- multithreaded servers can be problematic and therefore should generally be avoided unless you absolutely need to make use of multiple cores -- and even then it might be better to use multiple processes rather than multiple threads, for safety's sake.

这篇关于为什么套接字使用线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆