Questions tagged «multithreading»

多线程是计算机或程序通过利用多个并发的执行流(通常称为线程)来并发或异步执行工作的能力。

3
循环内的c ++线程输出错误的值
我试图理解c ++中的多线程,但是我陷入了这个问题:如果我在for循环中启动线程,它们会打印错误的值。这是代码: #include <iostream> #include <list> #include <thread> void print_id(int id){ printf("Hello from thread %d\n", id); } int main() { int n=5; std::list<std::thread> threads={}; for(int i=0; i<n; i++ ){ threads.emplace_back(std::thread([&](){ print_id(i); })); } for(auto& t: threads){ t.join(); } return 0; } 我原本希望打印出0、1、2、3、4的值,但是我经常两次得到相同的值。这是输出: Hello from thread 2 Hello from thread 3 …

4
Windows上的多线程Java应用程序的CPU使用率太低
我正在开发一个Java应用程序,用于解决一类数值优化问题-更确切地说是大规模线性编程问题。单个问题可以分解为多个较小的子问题,这些子问题可以并行解决。由于子问题多于CPU内核,因此我使用ExecutorService并将每个子问题定义为可提交给ExecutorService的Callable。解决子问题需要调用本机库-在这种情况下为线性编程求解器。 问题 我可以在Unix和具有多达44个物理核心和256g内存的Windows系统上运行该应用程序,但是在Windows上,大问题的计算时间比Linux上高一个数量级。Windows不仅需要大量内存,而且随着时间的推移,CPU利用率从开始时的25%下降到几个小时后的5%。这是Windows中任务管理器的屏幕截图: 观察结果 整个问题的大型实例的解决时间从数小时到数天不等,并且最多消耗32g的内存(在Unix上)。子问题的解决时间在ms范围内。 对于仅需几分钟即可解决的小问题,我不会遇到此问题。 Linux开箱即用地使用了两个套接字,而Windows要求我显式地激活BIOS中的内存交错,以便应用程序利用两个内核。但是,是否执行此操作不会对总体CPU利用率随时间的下降造成影响。 当我查看VisualVM中的线程时,所有池线程都在运行,没有一个正在等待。 根据VisualVM,90%的CPU时间花在了本机函数调用上(解决了一个小的线性程序) 垃圾回收不是问题,因为该应用程序不会创建和取消引用很多对象。而且,大多数内存似乎是堆外分配的。对于最大实例,Linux上4g的堆就足够了,而Windows上8g的堆就足够了。 我尝试过的 各种JVM arg,高XMS,高元空间,UseNUMA标志和其他GC。 不同的JVM(热点8、9、10、11)。 不同线性编程求解器(CLP,Xpress,Cplex,Gurobi)的不同本机库。 问题 是什么导致大量使用本地调用的大型多线程Java应用程序在Linux和Windows之间的性能差异? 在实现方面有什么可以改变的,例如Windows,我是否应该避免使用接收数千个Callable的ExecutorService来代替呢?

2
使用函数对象的C ++线程,如何调用多个析构函数,而不是构造函数?
请在下面找到代码片段: class tFunc{ int x; public: tFunc(){ cout<<"Constructed : "<<this<<endl; x = 1; } ~tFunc(){ cout<<"Destroyed : "<<this<<endl; } void operator()(){ x += 10; cout<<"Thread running at : "<<x<<endl; } int getX(){ return x; } }; int main() { tFunc t; thread t1(t); if(t1.joinable()) { cout<<"Thread is joining..."<<endl; t1.join(); } …


2
Java ThreadPoolExecutor:动态更新核心池大小会间歇性地拒绝传入的任务
我遇到了一个问题,如果ThreadPoolExecutor在创建池之后尝试将核心池的大小调整为其他数字,那么RejectedExecutionException即使我提交queueSize + maxPoolSize的任务数从来没有超过,我也会间歇性地拒绝某些任务。 我试图解决的问题是扩展ThreadPoolExecutor,以基于坐在线程池队列中的挂起执行来调整其核心线程的大小。我需要这样做,因为默认情况下,只有在队列已满时,a ThreadPoolExecutor才会创建一个新的Thread。 这是一个演示了该问题的小型独立的Pure Java 8程序。 import static java.lang.Math.max; import static java.lang.Math.min; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class ThreadPoolResizeTest { public static void main(String[] args) throws Exception { // increase the number of iterations if unable to reproduce // for …

1
react-native是否支持多线程和后台线程或并行执行?我们该怎么做?
我浏览了react-native的官方文档以及一些其他媒体资源和博客,我才知道react-native 中有UI Thread和JavaScript Thread。Javascript线程是逻辑将在其中运行javascript代码的线程,将执行API调用,处理触摸事件等。UI线程将更新UI。 如果JavaScript线程正在处理该过程,并且如果我们再次执行按钮操作或任何其他触摸事件,则需要花费一些时间来进行响应,在完成一个过程之后,仅UI Updates会出现滞后或卡在某处的感觉。 例如 有一个底部标签导航器,它有四个标签,第一个标签有一个列表视图,而地图视图则显示了第二个标签中多个点之间的路线 我在第一个标签页中执行了一些按钮操作(在列表视图中单击类似按钮),然后立即导航到第二个标签页,感觉在更新UI上有些滞后,或者从第一个标签页导航需要一些时间(1-3秒)标签到第二个标签 在第二个选项卡中,如果我导航到任何其他选项卡,则该地图将花费时间(5-10秒)来获取多个点之间的路线。如果我导航到任何其他选项卡,则选项卡之间的导航并不流畅,并且存在大量UI滞后。 我们如何才能使本机应用程序更快地响应可触摸的操作并减少UI滞后 有没有多线程和后台线程的概念,我们可以在主线程中运行特定的逻辑并更新UI,以使本机应用程序更快地响应而不会出现滞后。

4
cppreference中对宽松顺序的解释是否错误?
在cppreference.com的文档中std::memory_order,有一个宽松订购的示例: 轻松订购 带标签的原子操作memory_order_relaxed不是同步操作;它们不会在并发内存访问之间强加顺序。它们仅保证原子性和修改顺序的一致性。 例如,如果x和y最初为零, // Thread 1: r1 = y.load(std::memory_order_relaxed); // A x.store(r1, std::memory_order_relaxed); // B // Thread 2: r2 = x.load(std::memory_order_relaxed); // C y.store(42, std::memory_order_relaxed); // D 被允许以产生R1 == R2 == 42,因为尽管A被测序-之前线程1中B和C 之前测序线程2内d,没有什么阻止由在y的修改次序出现A之前D和B,从按x的修改顺序出现在C之前。D在y上的副作用对于线程1中的负载A可见,而B在x上的副作用对于线程2中的负载C可见。特别是,如果D在C in之前完成,则可能发生这种情况。线程2,由于编译器重新排序或在运行时。 它说:“在线程2中,C在D之前被排序”。 根据可以在评估顺序中找到的按顺序排序的定义,如果A在B之前排序,则A的评估将在B的评估开始之前完成。由于C在线程2中在D之前被排序,因此C必须在D开始之前完成,因此快照的最后一句的条件部分将永远无法满足。

2
Java指派执行程序由于某种原因失败时,停止执行程序服务
我需要某种服务,该服务将在1秒的间隔内同时运行1分钟1分钟。 如果其中一项任务失败,则我想停止该服务,并停止运行该服务的每个任务,并带有某种指示错误的指示器,否则,如果在一分钟后一切正常,则该服务将停止并指示所有指示器均正常运行。 例如,我有2个功能: Runnable task1 = ()->{ int num = Math.rand(1,100); if (num < 5){ throw new Exception("something went wrong with this task,terminate"); } } Runnable task2 = ()->{ int num = Math.rand(1,100) return num < 50; } ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2); task1schedule = scheduledExecutorService.scheduleAtFixedRate(task1, 1, 60, TimeUnit.SECONDS); task2schedule = …

3
“ volatile”对于多核系统的可移植C代码是否有任何保证?
看着经过一大堆 的 其他 问题 和 他们的 答案,我得到的印象是有什么在C“挥发性”关键字表示正好没有广泛的协议。 即使标准本身似乎也不够清晰,每个人都无法理解其含义。 除其他问题外: 根据您的硬件和编译器,它似乎提供了不同的保证。 它影响编译器优化,但不影响硬件优化,因此在执行自己的运行时优化的高级处理器上,甚至不清楚编译器是否可以阻止您要阻止的任何优化。(某些编译器确实会生成指令来阻止某些系统上的某些硬件优化,但这似乎并未以任何方式进行标准化。) 总结一下问题,似乎(经过大量阅读)“ volatile”保证了类似的结果:该值将不但从/向寄存器,而且至少向内核的L1缓存中读/写,其顺序与读/写出现在代码中。但这似乎没有用,因为在同一个线程中读/写寄存器已经足够,而与L1缓存协调并不能保证与其他线程的协调。我无法想象仅与L1缓存进行同步的重要性。 用途1 唯一广泛同意使用volatile的似乎是旧的或嵌入式系统,其中某些内存位置通过硬件映射到I / O功能,例如内存中的某个位(直接在硬件中)控制灯光。 ,或告诉您键盘按键是否按下的内存中的某个位(因为它是通过硬件直接连接到按键的)。 看来,“用1”不移植的代码,其目标包括多核系统发生。 USE 2 与“ use 1”没什么不同,它是可由中断处理程序(可以控制灯光或从键存储信息)随时读取或写入的内存。但是为此已经存在一个问题,即取决于系统,中断处理程序可能会在 具有自己的内存缓存的不同内核上运行,并且“ volatile”不能保证所有系统上的缓存一致性。 因此,“使用2”似乎超出了“易失性”所能提供的范围。 用途3 我看到的唯一其他无可争议的用途是防止通过不同变量指向指向编译器未意识到的相同内存的不同内存的访问优化。但这可能只是无可争议的,因为人们没有在谈论它-我只看到其中一个提及。而且我认为C标准已经认识到“不同”的指针(例如指向函数的不同args)可能指向同一项目或附近的项目,并且已经指定编译器必须生成即使在这种情况下也可以工作的代码。但是,我无法在最新的标准(500页!)中快速找到此主题。 那么“使用3”也许根本不存在? 因此,我的问题是: 在多核系统的可移植C代码中,“ volatile”是否完全可以保证? 编辑-更新 浏览最新标准后,答案似乎至少是非常有限的: 1.标准针对特定类型“ volatile sig_atomic_t”反复指定特殊处理。但是该标准还说,在多线程程序中使用信号功能会导致不确定的行为。因此,该用例似乎仅限于单线程程序与其信号处理程序之间的通信。 2.该标准还为setjmp / longjmp指定了“ volatile”的明确含义。(在其他问题和答案中给出了重要示例代码)。 因此,更精确的问题变成了: 除了(1)允许单线程程序从其信号处理程序接收信息之外,还是(2)允许setjmp,“ volatile”是否可以保证多核系统的可移植C代码中的任何内容?代码以查看在setjmp和longjmp之间修改的变量? 这仍然是一个是/否问题。 如果为“是”,那么最好显示一个无错误的可移植代码示例,如果省略了“ volatile”,则该示例会出现错误。如果为“ no”,那么我认为对于多核目标,在这两种非常特殊的情况下,编译器可以随意忽略“ volatile”。

1
是否可以限制C ++ 17并行`for_each`的线程数?
我使用std::for_eachwith std::execution::par对表示为结构向量的巨大输入执行复杂的计算。该计算不需要任何与硬件有关的延迟(例如,网络或磁盘IO),它是“仅CPU”计算。对我来说,逻辑上讲,没有必要创建我们拥有硬件的更多OS线程;但是,Visual C ++ 2019平均创建50个线程,有时甚至只有12个硬件线程,最多可以创建500个线程。 有没有办法来限制并行线程计数至hardware_concurrency与std::for_each和std::execution::par,或创建合理的线程数是使用自定义代码的唯一途径std::thread?

2
WebView何时准备好使用snapshot()?
JavaFX的文档状态,一个WebView当准备Worker.State.SUCCEEDED达到但是,除非你稍等片刻(即Animation,Transition,PauseTransition等等),一个空白页面的呈现方式。 这表明在WebView内部发生了一个事件,准备将其捕获,但这是什么? GitHub上SwingFXUtils.fromFXImage有7,000多个使用的代码片段,但其中大多数似乎与无关WebView,是交互式的(人为掩盖种族条件)或使用任意的Transitions(从100ms到2,000ms的任何地方)。 我试过了: 在的尺寸changed(...)范围内进行监听WebView(height和width属性DoubleProperty实现ObservableValue,可以监视这些东西) 🚫不可行。有时,该值似乎与绘制例程分开更改,从而导致部分内容。 盲目地告诉runLater(...)FX应用程序线程上的所有内容。 techniques许多技术都使用此方法,但是我自己的单元测试(以及其他开发人员的一些反馈)解释说,事件通常已经在正确的线程上,并且此调用是多余的。我能想到的最好的办法就是通过排队,对某些人起作用而增加了足够的延迟。 将DOM侦听器/触发器或JavaScript侦听器/触发器添加到 WebView despite SUCCEEDED尽管捕获了空白,但在调用JavaScript和DOM时似乎都正确加载了。DOM / JavaScript侦听器似乎无济于事。 使用Animation或Transition来有效地“休眠”而不会阻塞主FX线程。 This️这种方法行之有效,如果延迟足够长,则可以产生高达100%的单元测试,但是过渡时间似乎是我们猜测和设计不佳的未来时刻。对于高性能或关键任务应用程序,这迫使程序员在速度或可靠性之间进行权衡,这两者都是用户的潜在不良体验。 什么时候可以打电话WebView.snapshot(...)? 用法: SnapshotRaceCondition.initialize(); BufferedImage bufferedImage = SnapshotRaceCondition.capture("<html style='background-color: red;'><h1>TEST</h1></html>"); /** * Notes: * - The color is to observe the otherwise non-obvious cropping that occurs * with some techniques, such as `setPrefWidth`, `autosize`, etc. …

1
开始后分离一个生成子进程
我以这种方式启动生成子进程: let process = spawn(apiPath, { detached: true }) process.unref() process.stdout.on('data', data => { /* do something */ }) 当我开始该过程时,我需要使其保持连接状态,因为我想读取其输出。但是在关闭我的Node进程(父进程)之前,我想分离所有未完成的子进程以使其在后台运行,但是正如文档所述: 使用分离选项启动长时间运行的进程时,除非父进程没有提供未连接到父进程的stdio配置,否则该进程将在父进程退出后不会在后台继续运行。 但是,使用该选项,stdio: 'ignore'我无法阅读,stdout这是一个问题。 我尝试在关闭父进程之前手动关闭管道,但未成功: // Trigger just before the main process end process.stdin.end() process.stderr.unpipe() process.stdout.unpipe()

5
如何为每个请求项创建多个线程
我正在尝试在订单级别使用多线程处理以下代码。 List<String> orders = Arrays.asList("order1", "order2", "order3", "order4", "order1"); 当前顺序执行: orders.stream().forEach(order -> { rules.forEach(rule -> { finalList.add(beanMapper.getBean(rule) .applyRule(createTemplate.apply(getMetaData.apply(rule), command), order)); }); }); 我尝试使用: orders.parallelStream().forEach(order -> {}} // code snippet. 但是它正在更改rules.forEach(rule-> {}}的顺序。 例如: 输入: List<String> orders = Arrays.asList("order1", "order2", "order3", "order4", "order1"); List<String> rules = Arrays.asList("rule1", "rule2", "rule3"); 预期产量: order1 with …

1
“在此之前发生”是什么意思?
在C ++草案标准中多次使用“强烈发生于”这一短语。 例如:终止 [basic.start.term] / 5 如果具有静态存储持续时间的对象的初始化强烈发生在对std :: atexit的调用之前(请参见[support.start.term]),则对该函数的调用将传递给std :: atexit在调用对象的析构函数之前进行排序。如果对std :: atexit的调用强烈发生在具有静态存储持续时间的对象的初始化完成之前,则在调用传递给std :: atexit的函数之前对对象的析构函数的调用进行排序。如果对std :: atexit的调用在另一次对std :: atexit的调用之前强烈发生,则传递给第二个std :: atexit的函数的调用在传递给第二个std :: atexit的函数之前被排序。第一个std :: atexit调用。 并在 数据竞赛 [intro.races] / 12中定义 评估A发生在评估D之前,如果发生以下情况之一 (12.1)A在D之前排序,或 (12.2)A与D同步,并且A和D都是顺序​​一致的原子操作([atomics.order]),或 (12.3)对B和C进行求值,使得A在B之前排序,B仅发生在C之前,而C在D之前排序,或者 (12.4)有一个评估B,使得A强烈发生在B之前,而B强烈发生在D之前。 [注意:非正式地,如果A强烈地发生在B之前,那么在所有情况下A似乎都在B之前被评估。强烈发生在排除消耗操作之前。—尾注] 为什么引入“强烈发生”?直觉上,它与“之前发生的事情”有什么区别和关系? 注释中的“在所有情况下,似乎A在B之前都被评估”是什么意思? (注意:此问题的动机是Peter Cordes在此答案下的评论。) 标准报价附加草案(感谢Peter Cordes) 有序性和一致性[atomics.order] / 4 所有memory_order :: seq_cst操作(包括篱笆)上都有一个总顺序S,它满足以下约束。首先,如果A和B是memory_order ::: seq_cst运算,并且A强烈地发生在B之前,那么A在S中先于B.其次,对于对象M上的每对原子操作A和B,A的相干性在B之前,S必须满足以下四个条件: …


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.