美文网首页
Rust 共享并发状态

Rust 共享并发状态

作者: virct | 来源:发表于2019-08-04 16:39 被阅读0次

线程通讯方式

线程之间的通讯方式最常见的就是通过共享内存的方式,再通过加锁保护数据在多个线程中的一致性。
Rust语言同样有这种支持那就是Mutex<T>互斥器。

互斥器

通过互斥器可以申明一个数据是互斥的,要使用互斥器中的数据必须持有锁,当离开作用域之后会自动释放锁


mutex.png

多线程中使用互斥器

        //java code
        AtomicInteger counter = new AtomicInteger(0);
        for(int i = 0 ; i< 3 ; ++i)
            new Thread(()-> counter.addAndGet(1)).start();
        Thread.sleep(1000);
        assert 3==counter.get();

上面是Java中多个线程共同操作同一个线程安全的状态。通过for循环创建三个线程,线程间共享一个线程安全的计数器变量,完成计数操作。

下面通过Rust完成同样的操作。需要注意的是Rust中的所有权,当通move将外部counter的所有权转移到线程内之后外部作用域是无法操作counter的。因此这里需要使用引用计数智能指针,Rc<T>引用计数指针是非线程安全的,因此需要使用Arc<T>(原子引用计数)来通过牺牲部分性能的方式保证线程安全。

    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];
    for _ in 0..3{
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut hold_lock = counter.lock().unwrap();
            *hold_lock+=1;
        });
        handles.push(handle);
    }
    for handel in handles {
        handel.join().unwrap();
    }
    assert_eq!(*counter.lock().unwrap(),3);

死锁

Rust并不能完全避免死锁或“线程不安全”,下面是一段产生死锁的代码。

fn dead_lock(){//This is a dead lock code
    let p = Arc::new(Mutex::new(0));
    let q = Arc::clone(&p);
    let th = thread::spawn(move || {
        let mut i = p.lock().unwrap();
        //*i+=1;
    });
    let mut j = q.lock().unwrap();
    //*j+=1;
    th.join().unwrap();
}

主线程率先拿到锁,之后等待th线程结束,th线程此时由于锁被主线程拿到了需要等待主线程释放锁才能获取锁,因此th线程会一直等待主线程释放,主线程会一直等待th线程执行完毕,最终两个线程会永远等待下去。

解决方案就是在th.join().unwrap();之前释放掉主线程拿到的锁,因此可以将let mut j = q.lock().unwrap();放入一个代码块

// let mut j = q.lock().unwrap();
{let mut j = q.lock().unwrap();}

通过前面所讲到的离开作用域即释放锁这一特性来保证锁被提前释放。

总结

使用Rust 中的 Mutex(互斥器)能够在线程之间共享状态,使用流程大致是

  1. 在使用数据之前尝试获取锁(object.lock().unwrap())。
  2. 处理完被互斥器所保护的数据之后,必须解锁数据,这样其他线程才能够获取锁(离开作用域)。

其中释放锁是通过实现Drop trait来完成的,Rust并不能逻辑错误导致的死锁,因此编写代码时要注意合适取锁合适释放,避免逻辑错误。

相关文章

  • Rust 共享并发状态

    线程通讯方式 线程之间的通讯方式最常见的就是通过共享内存的方式,再通过加锁保护数据在多个线程中的一致性。Rust语...

  • Rust:线程间共享数据

    Rust通过独特的编译期检查,在很大程序上阻止了难懂的并发bug。 本文探索Rust线程间共享数据的方式。 我们用...

  • Java内存模型精讲

    1.JAVA 的并发模型 共享内存模型 在共享内存的并发模型里面,线程之间共享程序的公共状态,线程之间通过读写内存...

  • Rust 1.7 稳定版发布

    Rust 1.7 正式发布,Rust 是一个系统编程语言,专注于安全,速度和并发。 可以从官网直接安装 Rust ...

  • rust 并发

    1、启动子线程 2、线程异常 3、同步等待子线程执行完毕 4、子线程访问外部数据 5、共享可变数据 1. rust...

  • 提示57-58

    今天学习有关并发的内容,先看提示: 提示57 共享状态是不正确的状态。提示58 随机故障通常是并发问题。 作者用餐...

  • 【RUST_BASIC】Rust 并发

    1 线程 调用 thread::spawn 函数创建线程并传递一个闭包,包含新线程运行的代码: 使用 join 等...

  • Java内存模型学习

    并发编程模型分类:共享内存:线程之间共享程序的公共状态,线程之间通过写-读内 存中的公共状态来隐式进行通信消息传递...

  • [Java 并发]并发编程实战笔记-对象的共享

    java 对象的共享 要编写正确的并发程序,关键在于在访问共享可变状态是需要进行正确的管理,下面介绍如何共享和发布...

  • 【并发编程】- 内存模型(针对JSR-133内存模型)篇

    并发编程模型 1.两个关键问题 1)线程之间如何通信 共享内存程之间共享程序的公共状态,通过写-读内存中的公共状态...

网友评论

      本文标题:Rust 共享并发状态

      本文链接:https://www.haomeiwen.com/subject/xbtydctx.html