由于以下两个主要原因,阻塞线程被认为是不好的做法:
以下是我遇到这些原因的困难:
非阻塞,异步代码也应该花费几乎相同的内存量,因为调用堆栈应该正确执行他异步调用(背景前的地方保存的保存,毕竟).如果线程效率非常低(内存方面),为什么OS/CLR不提供更轻量级的线程(只保存callstack的上下文而不是其他内容)?它不是一个更清洁的内存问题解决方案,而不是强迫我们以异步方式重新构建我们的程序(这更复杂,更难理解和维护)?
当线程被阻塞时,操作系统将其置于等待状态.操作系统不会上下文切换到休眠线程.由于超过95%的线程生命周期花费在休眠上(假设这里有IO绑定的应用程序),性能命中应该可以忽略不计,因为线程的处理部分可能不会被操作系统抢占,因为它们应该跑得很快,做得很少.因此,在性能方面,我无法看到非阻塞方法带来很多好处.
我在这里错过了什么或为什么这些论点有缺陷?
有人告诉我,对于I/O绑定的应用程序,非阻塞I/O会更好.对于CPU绑定应用程序,阻塞I/O要好得多.我找不到这种说法的理由.试过谷歌,但很少有文章只涉及这个话题没有太多细节.有人可以提供深度理由吗?
有了这个,我想清楚自己,非阻塞I/O的缺点是什么.
通过另一个线程会后在这里,一个原因,我可能涉及在外面是如果I/O过程是沉重得那么只有我们使用非阻塞I/O可以看到显著的性能提升.它还指出,如果I/O操作的数量很大(典型的Web应用程序场景),其中有许多请求寻找I/O请求,那么我们也看到使用非阻塞I/O的重大改进.
因此,我的问题归结为以下列表:
在CPU密集型应用程序的情况下,最好是启动线程池(或scala的executionContext)并在线程池的线程之间划分工作.(我想它肯定比产生自己的线程和手动划分工作更有优势还使用asyn未来概念,甚至可以使用回调返回CPU密集型工作,从而避免与阻塞多线程相关的问题?).此外,如果存在足够快的I/O,则使用线程池本身的线程上的阻塞原则来执行I/O. 我对吗?
在技术上使用非阻塞I/O实际上有什么缺点或开销?如果I/O足够快或者需要的I/O操作非常少,为什么我们看不到使用非阻塞I/O会带来多大的性能提升?最终它是处理I/O的操作系统.无论I/O的数量是大还是小,让操作系统处理这种痛苦.是什么让这里有所不同.
我有一个线程服务器.
需要在需要运行的线程上创建QTcpSocket,FI:Qt -通过传递套接字描述符在新线程中处理QTcpSocket.
我的问题是,我需要有一个线程池并在特定线程上移动套接字在客户端发送了一个特定的令牌后,该令牌定义了套接字需要的线程.
换句话说,我需要读取套接字以了解预先放置它的线程.
一些想法是首先绑定到QTcpSocket,读取,然后将描述符发送到线程并创建另一个QTcpSocket,但文档说:
注意:无法使用相同的本机套接字描述符初始化两个抽象套接字.
另一个解决方案是在一个单独的线程中创建套接字,然后将两个线程连接在一起,但我不知道是否可能.
或者也许能够在子线程上调用setSocketDescriptor之前读取主线程上的套接字描述符,如果可能的话?
你好,我认为使用 CompletableFuture 和默认设置ForkJoinPool我可以优化任务的执行而不是经典,ExecutorService但我错过了一些东西
使用此代码执行需要 1 秒,我有 3 个工作线程:
for (int i = 0; i < 3; i++) {
final int counter = i;
listTasks.add(CompletableFuture.supplyAsync(() -> {
Thread.sleep(1000);
System.out.println("Looking up " + counter + " on thread " + Thread.currentThread().getName());
return null;
}));
}
Run Code Online (Sandbox Code Playgroud)
好吧,看起来很正常。
但是使用此代码,需要 3 秒:
for (int i = 0; i < 9; i++) {
final int counter = i;
listTasks.add(CompletableFuture.supplyAsync(() -> {
Thread.sleep(1000);
System.out.println("Looking up " + counter + " on thread " …Run Code Online (Sandbox Code Playgroud) java multithreading asynchronous work-stealing completable-future
假设我已经打开dev/poll mDevPoll,我可以安全地调用这样的代码
struct pollfd tmp_pfd;
tmp_pfd.fd = fd;
tmp_pfd.events = POLLIN;
// Write pollfd to /dev/poll
write(mDevPoll, &tmp_pfd, sizeof(struct pollfd));
Run Code Online (Sandbox Code Playgroud)
...同时来自多个线程,或者我是否需要添加自己的同步原语mDevPoll?
通过阅读 Stack Overflow 上有关同步与异步的一些帖子,看来异步应该具有较小的开销,或者比阻塞 I/O 操作的同步调用更快:
我研究过的一些地方: 非阻塞 I/O 真的比多线程阻塞 I/O 更快吗?如何? Javascript 异步函数的开销是多少
我写了一个小型基准测试,制作 4 个 256MB 到 1GB 的文件来查看fs.readFile().
const {performance} = require('perf_hooks');
const fs = require('fs');
const {execSync} = require("child_process");
const sizes = [512, 1024, 256, 512]; //file sizes in MiB
function makeFiles() {
for (let i = 0; i < sizes.length; i++) {
execSync(`dd if=/dev/urandom of=file-${i}.txt bs=1M count=${sizes[i]}`, (error, stdout, stderr) => {
console.log(`stdout: ${stdout}`);
});
}
}
function syncTest() {
const startTime = …Run Code Online (Sandbox Code Playgroud) asynchronous ×3
blocking ×1
c ×1
c# ×1
cpu-speed ×1
fs ×1
java ×1
node.js ×1
nonblocking ×1
qt ×1
qtcpsocket ×1
qthread ×1
scalability ×1
solaris ×1
solaris-10 ×1
unix ×1