multithreading - 启用优化后,带有衍生线程的程序会出现困惑

标签 multithreading rust

当我使用 rustc 1.rs 编译以下代码时,它按预期无休止地运行。

use std::thread;

fn main() {
    thread::spawn(|| {
        let a = 2;
        loop {
            a*a;
        }
    }).join();
}

一个较短的版本:

use std::thread;

fn main() {
    thread::spawn(|| {
        loop {}
    }).join();
}

但是,如果我使用 rustc -O 1.rs 编译上面的两个程序,它们会崩溃:

thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Error { repr: Os { code: 0, message: "Success" } }', src/libcore/result.rs:837
stack backtrace:
1:     0x5650bd0acada - std::sys::imp::backtrace::tracing::imp::write::h917062bce4ff48c3
                        at /build/rustc-1.14.0+dfsg1/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:42
2:     0x5650bd0b068f - std::panicking::default_hook::{{closure}}::h0bacac31b5ed1870
                        at /build/rustc-1.14.0+dfsg1/src/libstd/panicking.rs:247
3:     0x5650bd0aee7c - std::panicking::default_hook::h5897799da33ece67
                        at /build/rustc-1.14.0+dfsg1/src/libstd/panicking.rs:263
4:     0x5650bd0af4d7 - std::panicking::rust_panic_with_hook::h109e116a3a861224
                        at /build/rustc-1.14.0+dfsg1/src/libstd/panicking.rs:451
5:     0x5650bd0af364 - std::panicking::begin_panic::hbb38be1379e09df0
                        at /build/rustc-1.14.0+dfsg1/src/libstd/panicking.rs:413
6:     0x5650bd0af289 - std::panicking::begin_panic_fmt::h26713cea9bce3ab0
                        at /build/rustc-1.14.0+dfsg1/src/libstd/panicking.rs:397
7:     0x5650bd0af217 - rust_begin_unwind
                        at /build/rustc-1.14.0+dfsg1/src/libstd/panicking.rs:373
8:     0x5650bd0e2f3d - core::panicking::panic_fmt::hcfbb59eeb7f27f75
                        at /build/rustc-1.14.0+dfsg1/src/libcore/panicking.rs:69
9:     0x5650bd0a6e84 - core::result::unwrap_failed::h15a0fc826f4081f4
10:     0x5650bd0b7ffa - __rust_maybe_catch_panic
                        at /build/rustc-1.14.0+dfsg1/src/libpanic_unwind/lib.rs:97
11:     0x5650bd0a6fc1 - <F as alloc::boxed::FnBox<A>>::call_box::he32a93ebea7bc7ad
12:     0x5650bd0ae6c4 - std::sys::imp::thread::Thread::new::thread_start::ha102a6120fc52763
                        at /build/rustc-1.14.0+dfsg1/src/liballoc/boxed.rs:605
                        at /build/rustc-1.14.0+dfsg1/src/libstd/sys_common/thread.rs:21
                        at /build/rustc-1.14.0+dfsg1/src/libstd/sys/unix/thread.rs:84
13:     0x7fc2d0042423 - start_thread
14:     0x7fc2cfb6e9be - __clone
15:                0x0 - <unknown>

如果我删除闭包中的所有代码,它会无错退出:

use std::thread;

fn main() {
    thread::spawn(|| {
    }).join();
}

如果我在循环中添加 println!(),它也能正常工作:

use std::thread;

fn main() {
    thread::spawn(|| {
        loop {
            println!("123")
        }
    }).join();
}

我在 Rust 1.14 和 1.15 上测试了这个,两者都出现了同样的问题。

这是因为我用错了什么还是有错误?

最佳答案

这是一个 known issue (#28728) .简而言之,LLVM 优化了 have no observable side-effects 的循环:

The implementation may assume that any thread will eventually do one of the following:

  • terminate
  • make a call to a library I/O function
  • access or modify a volatile object, or
  • perform a synchronization operation or an atomic operation

在这种情况下,这些都不成立,因此 LLVM 完全删除了循环。然而,Rust 编译器生成的代码假定循环永远不会返回。这种不匹配会导致崩溃。

因为没有副作用的无限循环基本上是没有用的,这个问题是not of critical priority . Rust 团队目前是 waiting for LLVM to provide a better solution .

作为解决方法,您应该在循环内简单地做一些事情,这可能是您无论如何都想做的事情 ^_^

关于multithreading - 启用优化后,带有衍生线程的程序会出现困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42182573/

相关文章:

python 线程 - 将参数传递给线程的最佳方法

docker - 编译 azure iot edge 的 edgelet 模块时出现 cargo 错误

multithreading - 无法在生成的线程中调用函数,因为它是 "does not fulfill the required lifetime"

multithreading - 由于线程化,将值移出闭包

rust - Rust 中结构的惯用迭代器 + 突变?

c++ - 实现低优先级后台线程的模式?

multithreading - 线程 101 : What is a Dispatcher?

java - 如何以最有效的方式在大量文件中搜索某个搜索词?

基于可用 FREE cpu 的 Java 并发性

rust - 为什么对原语的引用没有隐式取消引用