Rust多线程之数据共享

我们都知道Java中通过实现Runnable接口或继承Thread类,来完成一个线程的创建,那么在Rust中是如何实现一个线程的呢?代码如下。

fn how_to_create_a_thread(){
    // 创建一个线程
    let thread_handle = thread::spawn(|| {
        println!("Thread inner");
    });
    // 阻塞线程,并等待其自己执行完毕
    thread_handle.join().unwrap();
}

在Rust中,在 std::thread,可以直接通过 thread::spawn(||{})方式创建出一个线程,并且返回该线程 JoinHandle,可以通过 JoinHandle进行join操作。

不难猜出,同Java类似,通过加锁的方式保证其数据安全。我们来看具体实现代码。

fn test_single_thread(){
    let m = Mutex::new(5);
    {
        let  mut num = m.lock().unwrap();
        *num = 6;
    }
    println!("m = {:?}", m);
}

在Rust中,通过 std::sync::Mutex类, Mutex::new(t: T),将需要共享的数据放进去即可,通过,lock()方法,对数据加锁并获取数据,这样就可以对加锁的数据进行操作。 但是与Java有所不同的是:Rust中的锁实现了Drop接口,会自动释放,不需要手动Unlock。用Java代码解释,就是类似实现了 AutoCloseable接口,可以实现自动关闭。代码如下:

public class Mutex implement AutoCloseable{
    public void close() throws Exception{
    }
}
try(Mutex mut = new Mutex(5)){

}

单线程实现数据共享看起来蛮简单的,直接创建一个线程,然后运行就完了,就看不出来。那如何实现多线程呢?代码如下:

// 多线程和锁
fn test_mulit_thread() {
    // 使用Arc实现clone功能
    // 对Mutex::new生成的对象实现clone功能
    // 如果不实现clone,只能移动一次
    let lock_sub = Arc::new(Mutex::new(0));

    let mut thread_list = vec![];

    for _ in 0..10 {
        // clone 锁对象,否则下方 move一次后,其他for循环将获取不到锁对象
        let lock = Arc::clone(&lock_sub);

        let thandle = thread::spawn(move || {
            let mut num = lock.lock().unwrap();
            *num += 1
        });
        thread_list.push(thandle);
    }

    for handle in thread_list {
        handle.join().unwrap();
    }
    println!("Result  : {}", *lock_sub.lock().unwrap());

上方例子是标准实现多线程数据共享的方式。其实有如下疑问,可以说一下。

通过上面的方式实现了多线程,其实还有蛮多疑问的, 如果我就是不用Arc对象,而是采用普通对象,或者说Rc对象了,就真的不能实现多线程间的数据共享吗?

普通对象即:直接一个对象。 这有的方式不行,因为多线程间共享变量就必须用到多个对象,即对象的多副本,那么就要实现Rc对象。

通过Rc对象,来实现多线程数据共享,代码如下。

fn test_mulit_thread_by_rc() {

    let lock_sub = Rc::new(Mutex::new(0));

    let mut thread_list = vec![];

    for _ in 0..10 {
        let lock = Rc::clone(&lock_sub);

        let thandle = thread::spawn(move || {
            let mut num = lock.lock().unwrap();
            *num += 1
        });
        thread_list.push(thandle);
    }

    for handle in thread_list {
        handle.join().unwrap();
    }
    println!("Result  : {}", *lock_sub.lock().unwrap());
}

代码同Arc没什么不同,就是把Arc对象换成Rc对象,然后试着编译。出现如下错误:

45  |           let thandle = thread::spawn(move || {
    |  _______________________^^^^^^^^^^^^^_-
    | |                       |
    | |                       std::rc::Rc> cannot be sent between threads safely

标红的提示:::rc::Rc

fn test_mulit_thread_by_rc() {
    let lock_sub = Rc::new(0);
    let mut thread_list = vec![];
    for _ in 0..10 {
        let mut lock = Rc::clone(&lock_sub);

        let thandle = thread::spawn(move || {
            *lock += 1
        });
        thread_list.push(thandle);
    }
    for handle in thread_list {
        handle.join().unwrap();
    }
    println!("Result  : {}", *lock_sub);
}

我放弃锁了,不加锁,能行吗? 通过编入后,还是出现了 std::rc::Rc<:sync::mutex>></std::sync::mutex` cannot be sent between threads safely这个错误,看来和Mutex对象没有关系啦。

本文主要讲述了如何实现线程,多线程,以及线程间的数据共享问题。但是我们知道,在多线程中,多线程操作数据,会出现死锁等问题,这个还没有说道。以后在慢慢聊。希望本文对大家有所帮助。谢谢!

Original: https://www.cnblogs.com/lifacheng/p/13332934.html
Author: 编号94530
Title: Rust多线程之数据共享

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/616360/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • SpringBoot 2.3 整合最新版 ShardingJdbc + Druid + MyBatis 实现分库分表

    今天项目不忙,想搞一下shardingJDBC分库分表看看,主要想实现以下几点: 舍弃xml配置,使用.yml或者.properties文件+java的方式配置spring。 使用…

    Java 2023年6月5日
    086
  • Java后端代码规范与优化建议

    1、尽量指定类、方法的final修饰符 带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如java.lang.String,整个类都是f…

    Java 2023年5月29日
    072
  • Qt学习笔记

    联系方式 QQ: 2653728884 ,加Q请注明添加原因! Original: https://www.cnblogs.com/arminker/p/5121596.htmlA…

    Java 2023年6月6日
    087
  • 面试常问的dubbo的spi机制到底是什么?

    前言 dubbo是一款微服务开发框架,它提供了 RPC通信 与 微服务治理 两大关键能力。作为spring cloud alibaba体系中重要的一部分,随着spring clou…

    Java 2023年6月16日
    0114
  • 老生常谈系列之Aop–JDK动态代理的底层实现原理

    老生常谈系列之Aop–JDK动态代理的底层实现原理 前言 在Aop系列里面有两篇文章,分别是老生常谈系列之Aop–Spring Aop原理浅析和老生常谈系列…

    Java 2023年6月8日
    086
  • leetcode 538. Convert BST to Greater Tree 把二叉搜索树转换为累加树(简单)

    一、题目大意 给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node…

    Java 2023年6月14日
    068
  • 2、springboot+mybatis+ajax+pageHelper+idea+maven(全套增删改查)

    0.构建项目 1、项目结构如下 2、编辑pom.xml文件配置依赖 1 <?xml version="1.0" encoding="UTF-8&…

    Java 2023年6月13日
    090
  • 请求合并与拆分在并发场景中应用

    一、序言 在并发场景中,当热点缓存Key失效时,流量瞬间打到数据库中,此所谓缓存击穿现象;当大范围的缓存Key失效时,流量也会打到数据库中,此所谓缓存雪崩现象。 当使用分布式行锁时…

    Java 2023年6月6日
    077
  • harbor安装

    Harbor 简介 Docker容器应用的开发和运行离不开可靠的镜像管理,虽然Docker官方也提供了公共的镜像仓库,但是从安全和效率等方面考虑,部署我们私有环境内的Registr…

    Java 2023年6月15日
    0108
  • 十六、多线程(基础)(完结)

    十六、多线程(基础) 16.1 线程相关概念 16.1.1 程序 是为完成特定任务、用某种语言编写的一组指令的集合。 简单的说:就是我们写的代码 16.1.2 进程 进程是指运行中…

    Java 2023年6月5日
    0141
  • jsp中在java里面怎么调文本框里面的值?

    jsp中在java里面怎么调文本框里面的值 方法一: 方法二: Original: https://www.cnblogs.com/muhy/p/14827596.htmlAuth…

    Java 2023年5月29日
    078
  • Git命令集锦

    Git命令集锦 前言 正文 主体git操作 TEST 列出所有本地分支: git branch 列出所有远程分支: git branch -r 列出所有本地分支和远程分支: git…

    Java 2023年6月5日
    089
  • Java AbstractQueuedSynchronizer(AQS)

    AbstractQueuedSynchronizer 为 java.util.concurrent.locks 包下的一个抽象类,简称 AQS( 抽象队列同步器)。 并发包(JUC…

    Java 2023年5月29日
    0110
  • Spring

    Spring实现简化开发的四项策略: 1、基于POJO的轻量级和最小侵入式编程; 2、通过依赖注入和面向接口编程实现松耦合; 3、基于切面和惯例进行声明式编程; 4、通过切面和模板…

    Java 2023年6月8日
    081
  • 2020-为什么换了工作

    摘要 经历了一个特殊的2020上半年,疫情出乎意料的持续了半年之久,还是没有看到结束的趋势。虽然外部环境很恶劣,还是做出了个人的重大选择,换工作。期间纠结了很久,毕竟工作就是生活,…

    Java 2023年6月8日
    090
  • 【前端】在浏览器控制台,直接发Ajax请求

    我们在日常的开发的过程中,经常需要前端测试发送请求测试一些数据。但是由于一些session,cookie的存在,我们无法在postman上创建一些会话。那么这样,我们就可以在浏览器…

    Java 2023年6月7日
    089
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球