Rust中的mutex与other language的mutex对比
直接上代码:
GO
先上靶子来批判。
package main
import (
"fmt"
"time"
"sync"
)
func main() {
var wg sync.WaitGroup
var(
mt sync.Mutex
a string
)
a = "I am in Main thread"
wg.Add(1)
go func() {
mt.Lock()
a = "I am in Sub-thread"
fmt.Printf("**SUB** thread [1]: %v \n", a)
time.Sleep(3 * time.Second)
fmt.Printf("**SUB** thread [2]: %v \n", a)
mt.Unlock()
wg.Done()
} ();
time.Sleep(time.Second)
a = "I am in Main thread"
fmt.Printf("**MAIN** thread [3]: %v \n", a)
wg.Wait()
}
expected result:
➜ tmp git:(master) ✗ go run mutex_error_using.go
**SUB** thread [1]: I am in Sub-thread
**SUB** thread [2]: I am in Sub-thread
**MAIN** thread [3]: I am in Main thread
running result:
➜ tmp git:(master) ✗ go run mutex_error_using.go
**SUB** thread [1]: I am in Sub-thread
**MAIN** thread [3]: I am in Main thread
**SUB** thread [2]: I am in Main thread
预期是通过加锁使得子线程临界区(Lock,Unlock之间的内容被锁上)。通过观察可以发现[3]这里直接修改a
的值。使得子线程里第二次获取到的a
的值是修改过的,与我们想象的结果有出入。这是因为go里的锁,就只是一个提示作用,怎么用还得看程序员。我们没有去获取锁的状态,直接修改了临界区内的值在编译器看来也是合理的。虽然这是一个很低级的错误,但是当碰上较大的工程的时候,所有人都有可能写出上面的代码。
Rust
use std::sync::Mutex;
fn main() {
let m = Mutex::new(5);
{
let mut num = m.lock().unwrap();
*num = 6;
}
println!("m is {:?}",m);
}
而Rust就不一样了,直接把要改变的值包在了Mutex里,无法绕开Mutex直接去改写里边的值。程序员就没法写出类似GO那种绕开锁的代码。