use std::sync::atomic::AtomicBool;
static FOO: AtomicBool = AtomicBool::new(false);
#[tokio::main]
async fn main() {
println!("foo: {:?}", FOO);
let bar = tokio::spawn(async move {
println!("foo: {:?}", FOO);
});
bar.await.unwrap();
}
在多线程编程下,如果不是全局变量,要用 Arc 来实现线程间传递,但在声明为 static 时不用Arc。
- 为什么在声明为 static 时不用 Arc ?是因为全局生命周期吗?
- 不理解 move 到 async 闭包的时候具体是什么发生了 move,是 FOO 的引用吗?还是 FOO 本身?
1
共 5 条评论, 1 页
评论区
写评论另外,官方文档也提到
谢谢几位大佬的回答,:-)
小结如下
Arc 是为了在多线程环境下跟踪共享变量的引用情况,确保变量被 drop 的时候没有被引用的情况。 static Atomic 是在多线程环境下,但因为其生命周期是全局的,比任何线程的生命周期都要长,所以不需要考虑通过 Arc 来跟踪。
move 是指变量的所有权发生移动,是作用域发生了变化。因为 statis Atomic 的作用域是全局的,所以根本不会发生move。 至于具体的实现,皮卡丘大佬提到是编译后被替换成固定的内存地址,这个还不懂,要继续研究研究。
在多线程编程下,如果不是全局变量,要用 Arc 来实现线程间传递
Arc是多个线程共享数据的一种办法,并非是唯一一个,比如还有Mutex等方式。
关键是共享的变量必须满足Sync的要求。Arc、Mutex、AtomicBool等类型无论全局还是局部变量都属Sync,所以同样都能共享。AtomicBool因为本身属Sync就不用再次包装了。
但在声明为 static 时不用Arc。
非static的Sync类同样不用Arc。
不理解 move 到 async 闭包的时候具体是什么发生了 move,是 FOO 的引用吗?还是 FOO 本身?
一般move会把变量的所有权移植到闭包里,闭包运行完了就drop删掉这些变量了,但是因为FOO是static它就一直存在且能保证不变,于是编译器没必要扯到所有权了,这一点前面的人也说了。
第一个问题,你看一下Arc的全名就行了Atomic reference counter。全局变量不需要reference counter,因为它完全不会被drop。
第二个问题,应该根本没有发生move。static是有静态生命周期而且全局可见的,在编译之后会被替换成固定的内存地址,所以根本不需要从main的scope里面获取FOO的reference。
Atomic 都是原子操作 有所有权又不是引用 为什么要Arc在打包一次?