问题标签 [starvation]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
multithreading - 为什么我的 goroutine 饿死了?
概述
我正在编写一个程序,其中在一个 goroutine 中启动服务器。服务器有几个不同的 goroutine :
- 主协程:它处理初始化,启动第二个协程来监听新的连接(2),然后进入一个无限循环来处理从连接(即客户端)接收到的数据。
- 监听 goroutine:这个 goroutine 进入一个无限循环,不断地监听新的连接。如果一个新的连接被接受,另一个 goroutine 被启动,它监听来自连接的消息,直到它被关闭。
服务器似乎运行良好。我可以成功添加许多新连接,并且在这些新连接最初被服务器接受后,我还可以在这些新连接上发送数据。
我的客户很简单。还有两个 goroutine:
- 主 goroutine:它处理初始化,向服务器注册客户端,启动第二个 goroutine 以从服务器读取数据 (2),然后进入无限循环以对从服务器接收到的数据进行操作。
- 第二个 goroutine:这个 goroutine 不断尝试从服务器读取数据,直到连接关闭。
饥饿
我在客户端的 goroutine 饥饿问题上遇到了很大的问题。具体来说,客户端的第二个 goroutine 总是饿死。这是饥饿的 goroutine 的来源:
我确信一条消息正在从服务器发送到客户端。我也确信正在发送的消息以protocol.EndOfMessage
. 我也确信我从服务器获取数据的方法是正确的,因为我使用相同的代码来注册客户端,而不是在无限循环中运行它,我允许它预先指定的尝试次数。
由于某种原因,我的客户不会收到数据。
为了确定我没有误解 goroutines 的性质,如果我用以下代码替换上面的代码:
goroutine 完全按预期工作:一切都像以前一样运行,但是“在接收者 goroutine 中!” 不断打印。因此,在这种情况下,例程肯定是正确执行的。
我的处理程序
现在,update(msg, debug)
只需调用fmt.Println(msg)
.
我能做些什么来彻底解决这个问题吗?我觉得放弃优先级/强制调度程序运行是解决这个问题的一个 hacky 解决方案。
php - PHP 群如何防止饥饿?
我有一个关于 PHP flock() 函数的问题:
PHPflock() 如何防止进程饥饿?
如果有一个进程 R 一直想要读取一个文件,而一个进程 W 想要在读取完成时写入文件(想要一个独占锁)。它如何使进程 W 不饿死?
有没有办法使用flock() 并使进程W 在PHP 中不会饿死?
java - 链表节点的线程安全切换,而不锁定整个列表
我正在学习线程、锁等。因此,我不想使用synchronized
关键字或任何thread-safe
其他类semaphore
和ReentrantLock
(没有原子变量)。
我想要一种同步LinkedList<T>
的Node<T>
,按大小排序T
(假设它T
是implements
一个interface
具有size
和increment
功能和lock
,unlock
功能)。我希望能够Nodes
用它们的T.getSize()
功能替换两个而不锁定所有列表。
例如,如果我只有一个线程,该函数将是一个“经典”替换函数,如下所示:
现在让我们来解决同步问题。
我想过尝试做类似的事情来lock
为我创建一个Nodes
:
问题是这并不是线程安全的,并且可能会发生死锁。例如,假设我们现在有Node a, Node b
那个a.next == b and b.prev==a
,如果线程 A 试图在 a 上使用替换函数,而线程 B 试图在 b 上使用替换函数,它们都将被锁定,我将无处可去。
如何使替换功能thread safe
没有lock
整个列表?我想避免dead-lock
and starvation
。
谢谢!
java - 垃圾收集器中的 Heap_lock 饥饿
垃圾收集器线程似乎饿死等待 Heap_lock。这是 GC 线程的堆栈跟踪
我的 Java 应用程序产生了大约 300 个线程。他们也会挨饿。这是一个堆栈跟踪示例:
运行我的应用程序几个小时后,饥饿就开始了。
我尝试了三个收集器:使用默认设置的 UseG1GC、UseParallelGC 和 UseConcMarkSweepGC,但仍然感到饥饿(没有尝试过串行 GC)。
我在 OSX 10.11.5 上使用 Java 1.8.0_92(构建 1.8.0_92-b14,Java HotSpot(TM) 64 位服务器 VM,构建 25.92-b14,混合模式)。
有足够的堆空间Xmx6G;我没有看到完整的 GC。我将 GC 线程 XX:VMThreadStackSize 的堆栈增加到 10MB,但得到了同样的饥饿。我还使用了较旧的 Java,同样饥饿。我没有看到任何致命错误日志 ( http://www.oracle.com/technetwork/java/javase/felog-138657.html )。
请建议如何调试这种饥饿。
2016 年 6 月 19 日更新:
我按堆栈跟踪对挂起的线程进行了分组,您可以看到
挂在 GangWorker::loop()
挂在 ConcurrentG1RefineThread::wait_for_completed_buffers()
编译器线程挂起
此外,其余线程具有这些堆栈跟踪(每个线程一行)
我省略了我的 300 个线程,因为 Java 不在安全点(jstack 不起作用),所以饥饿不能是因为我的(用户)线程。饥饿肯定是由 VM 线程引起的(我在上面列出的所有这些都带有堆栈跟踪)。
2016 年 6 月 24 日更新:
我做了jstack -F,我的线程被阻塞了,一些内存操作,比如这个
但 jstack 不显示垃圾收集器线程。为此,我在同一个进程上运行示例命令,就像在您看到饥饿的 GC 线程之前一样:
当我只用 30 个线程(而不是 300 个)运行我的应用程序时,饥饿就消失了。
我们需要找出垃圾收集器的__psynch_cvwait在哪个锁上等待,但是jstack没有说这个。可能代码检查是最好的选择。
c++ - 如何让作家线程饿死
我已经使用 C++14 的 shared_timed_mutex 编写了读写器问题的实现。在我看来,下面的代码应该会导致写入器饿死,因为太多的读取器线程一直在数据库上工作(在这个例子中是一个简单的数组):写入器没有机会获得锁。
当线程正在读取、写入、尝试以阻塞模式或通过try_lock()
方法获取锁时,我向标准输出添加了一些输出,但为了清楚起见,我删除了输出。我在 main 方法中进一步启动线程。当我运行程序时,编写器总是有机会写入数组(导致所有读取器线程阻塞,这没关系),但正如我上面所说,编写器根本不应该能够访问,因为有太多许多读取器线程从数组中读取。即使我根本不让读取线程进入睡眠状态(参数 0),写入线程也会以某种方式找到获取互斥锁的方法。那我怎么让作家饿死呢?
linux - linux进程调度程序如何防止进程饥饿
我读过linux内核包含许多调度类,每个类都有自己的优先级。为了选择一个新的进程来运行,进程调度程序从最高优先级迭代到最低优先级。如果在一个类中找到一个可运行的进程,则选择最高优先级的进程从该类运行。
摘自 Robert Love 的 Linux 内核开发:
进程调度的主要入口点是函数 schedule() ,定义在 kernel/sched.c 中。这是内核的其余部分用来调用进程调度程序的函数,决定运行哪个进程然后运行它。schedule() 对于调度程序类来说是通用的。也就是说,它找到具有可运行进程的最高优先级调度程序类,并询问它接下来要运行什么。鉴于此,schedule() 很简单也就不足为奇了。该函数的唯一重要部分——否则在这里重现太无趣——是它对 pick_next_task() 的调用,也在 kernel/sched.c 中定义。 pick_next_task() 函数遍历每个调度程序类,从最高优先级开始,并选择最高优先级类中的最高优先级进程。
让我们想象以下场景。有一些进程在较低优先级中等待,并且进程不断被添加到较高优先级中。低优先级的进程不会饿死吗?
ssl - 由于读取或写入期间无限重新协商而导致的 DoS
OpenSSL 和/或 SSL/TLS 协议是否提供某种针对无限重新协商的内置保护?
特别是,是否有可能SSL_read()
因为远程端(可能是恶意的)不断请求重新协商而不发送有效负载数据而永远继续执行?
我对此感到担心,因为我想使用轮询机制从单个线程为多个 SSL 连接提供服务,并确保一种公平形式,其中一个连接上的 I/O 处理不会导致 I/O 饥饿其他连接。
当我以非阻塞模式在套接字上调用常规read()
时,我知道它不能永远执行下去,因为缓冲区最终会填满。
但是,由于SSL_read()
可以透明地处理重新协商,在我看来,如果远程端(可能是恶意的)在不发送有效负载数据的情况下继续请求重新协商,并且底层传输层足够快以使底层读取和写入永远不会失败EWOULDBLOCK
,那么SSL_read()
可以最终永远执行,从而使其他连接挨饿。
因此我的问题是:OpenSSL 或协议是否有避免这种情况的机制?顺便说一句,这个问题同样适用SSL_write()
。
编辑:例如,我是否可以确定在进行多次重新谈判之前SSL_read()
会返回一个SSL_ERROR_WANT_READ
/SSL_ERROR_WANT_WRITE
指示,即使底层的读/写操作永远不会失败EWOULDBLOCK
?
编辑:出于这个问题的目的,假设我使用的是常规套接字 BIO ( BIO_s_socket()
),并且底层套接字处于非阻塞模式。
java - Spring Scheduler同步方法饥饿
假设我有一个调度程序
不同情况下不同的任务触发器会调用countIt。
当两个或多个job同时调用countIt时,会造成饥饿。
谁能告诉我是否有办法避免这种情况?
linux - 为什么我的程序中的这个线程会饿死?
我有一个有大约 80 个线程的程序。它在 linux 3.36 上运行在 ~50ish 核心机器上。最多有 2 个这样的程序同时运行,并且它们是相同的。机器上没有其他任何东西在运行。
线程本身是具有 SCHED_RR(循环)策略的实时 linux pthread。
- 10 是最高优先级(是的,我将 ulimit 设置为 99)并将 cpu 亲和性设置为 10 个核心。换句话说,它们都被固定在自己的核心上。
- 大约 60 个是中等优先级。
- 大约 10 个是低优先级。
10 个最高优先级的线程一直在使用 cpu。
其余的在做网络 IO 以及在 CPU 上做一些工作。问题是:我看到一个低优先级线程被饿死,有时一次超过 15 秒。此特定线程正在 TCP 套接字上等待某些数据。我知道数据已完全发送,因为我可以看到连接另一端的服务器已发送数据(即,它在发送数据后记录时间戳)。通常线程需要毫秒来接收和处理它,但偶尔会在其他服务器成功发送数据后需要 15 秒。请注意,增加线程的优先级并将其固定到 CPU 已经消除了这个问题,但这不是一个长期的解决方案。我一开始就没想到这种行为 - 15 秒是很长的时间。
有谁知道为什么会发生这种情况?我们已经排除它是程序/线程中的任何逻辑。另请注意,该程序是用 C 编写的。
c++ - 如何防止线程饥饿
我正在编写一个零延迟的云游戏服务器。这是一个软件管道。在第一阶段,我们捕获屏幕,在第二阶段,我们将其编码为视频。
然而,经过一段时间后,第二阶段冻结。我尝试了许多独立于平台的方法,但是它们中的任何一个最终都会冻结。How to prevent threads from starvation in C++11的答案表明我们应该使用互斥锁。我尝试过这个。它可以持续更长时间,但有时仍会冻结(很少)。我认为互斥锁也不是防止线程饥饿的明确提示。(也许我做错了?)
现在我同时使用互斥锁和禁用 Windows 优先级提升功能,但我根本不喜欢这个解决方案。谁能提供一个无饥饿的生产者和消费者的例子(在 C++11 中更好)?
生产商:
消费者:
最初我没有对循环队列做任何保护。我认为没有竞争条件(一个生产者和一个消费者)。然后我尝试添加互斥体但没有任何改变......