著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Rust同其前辈以及同侪一比,其勃勃野心也真的配得上其能力之卓越。
上一篇介绍了该语言的三大特色中的内存安全(compile-time memory safety)、零代价抽象(zero cost abstractions),
在本篇中,继续讲第三个---并发无忧(Fearless Concurrency)
03 并发无忧 (Fearless Concurrency)
谈及Rust的并行安全,意指该语言具有特定的应用程序编程接口(API)和抽象设定,这使正确安全的并发代码变得非常容易编写。
而C++,其并发代码中出错的概率依旧比期待的要高:当在C++中同步多个线程的数据访问时,需要在每次进入临界区时调用mutex.lock(),退出临界区时调用mutex.unlock():
临界区:这里是指一组需要自动执行的指令/语句。
于此,原则上没有其他线程可以中断临界区中当前正在执行的线程,并且在临界区中执行代码期间,任何线程都不会接触到中间值。
在多开发人员协作编写代码的大型代码库中,程序员可能会在从多个线程访问共享对象之前忘记调用互斥锁(mutex.lock),而这会导致数据竞争。
在其他情况下,又可能会忘记解除互斥锁的锁定,于是阻挡了其他想要访问数据的线程。
Rust对此有不同的做法,因其可以将数据封装在一个互斥类型(Mutex type)中,以确保从多个线程中同步可置换的数据访问信息:
在前面的C++代码中,是能够在对value调用lock()之后修改数据的。而Rust的理念是保护共享数据本身,而不是代码。
与C++不同,Rust的互斥锁和受保护数据的交互不是独立的。
如果不调用互斥锁类型的lock,就无法访问内部数据。那么如何释放锁呢?
调用lock()会返回一些叫做MutexGuard的东西,会在变量超出作用域时自动释放锁,这是Rust提供的众多安全并发抽象之一(细节部分将在后续专题中介绍)。
另一个新颖的想法是标记特征(Marker Traits)的概念,用于验证并确保在编译时同步和安全地访问并发代码中的数据。
当类型(Types)经过名为Send和Sync的标记特征注释后,可以用来指示程序对线程的发送和线程之间的共享是否安全。
当程序向线程发送一个值时,编译器检查该值是否实现了所需的标记特征,如果不是这样,则禁止该值的使用。
通过这种方式,Rust可以确保程序员放心的编写并发代码,而且编译器在编译时就可以捕获多线程代码中的错误。编写并发代码着实不易,而使用C/C++来做,整个过程容易变得麻烦丛生。
就当前材料科学的发展程度来看,短期内CPU很难明显提速(准确一点说,CPU时钟频率难以提升),于是计算机中增加了很多的核,以此为前提,并发编程是未来前进的方向。
感谢Rust使编写并发代码变得轻而易举,并且降低了许多人编写安全并发代码的门槛。
04 其他特色
Rust还借用了C++的RAII的规范来进行资源初始化。RAII(Resource Acquisition Is Initialization)
该技术基本上将资源的生存期与对象的生存期绑定,比如,堆分配类型的释放是通过由drop trait提供的drop方法执行,该功能会在变量超出作用域时自动调用。
Rust 利用结果(Result)和选项(Option)类型代替了空指针的概念,这意味着该语言不允许在代码中使用null/undefined值,
除非是在通过外部函数接口与其他语言交互以及使用不安全代码时。而且Rust强调组合而不是继承,并有一个特征系统(trait system),为该语言的主干,是由数据类型实现的,类似于Haskell中的typeclass.
与其他语言的比较
2020年8月中旬,Rust社区的自身成员,同时也是微软高级工程师的Ryan Levick,在Rust年度会议演讲中,将Rust与其他语言进行了一番对比。
本文在这里就这部分的演讲内容,回顾一下Rust的各种特性。
C
下图是微软做过的一份对自己产品的调查,指出近70%的问题来自于C/C++代码运行中出现的内存安全漏洞,
而使用Rust带来益处则在于,可以做到100%内存安全,而且是自动管理的,不必像C那样手动操控,这意味着使用Rust会减少近7成的Bug.
C++
除了C++同样面临的内存安全问题可以得以解决,Rust还拥有比C++更为新式,优雅和简单的语法,相对易学。
更为重要的是,Rust自有的构建工具,使代码开发,版本管理和测试等步骤变得更加规范和简易。
C#和Java
C#和Java都具有垃圾收集功能,不必担心内存安全问题。Rust对这两种语言表现出来的优化在于线程安全,而且是100%安全,不会出现数据竞争的情况。
Go和Node
相对这两种语言,Rust代码体现出了很强的稳健性(Robustness),这一点是由其强大的类型系统和错误处理体系支撑。
在Rust中,几乎可以做到,只要编译成功,便可以正常运行,这是因为许多问题在编译阶段就已经解决。
kotlin和Node
在开发App实现高层功能时,经常难以确定底层实现的细节,或不知如何控制具体的设置。
而使用Rust则可以对代码和资源分配进行全局管控,由于零代价抽象,可以作为注释,使程序更加具有可读性。
同时Rust的默认设定,也优化了App开发过程的理路。
Python和Ruby
也可以在这个队列中加入PHP,甚至是R,除了同样简易或所谓优雅的语法,
Rust能为这个队列开发者带来的益处是可以与C/C++语言相媲美的运行效率,甚至在某些场合,运行效率还在其上。
JavaScript和TypeScript
这表明Rust可以插手去开发前端应用,也就是说,在这个领域的开发者们,又多了一种选择。
完备的社区
Rust的社区非常活跃和友好,并且该语言有全面的文档,可见在:
https://doc.rust-lang.orgdoc.rust-lang.org
Stack Overflow的开发者调查已经连续三年(2016年、2017年和2018年)将Rust评为最受欢迎的编程语言,可以说整个编程社区都对Rust非常感兴趣。
总而言之,如果您的目标是编写性能高、bug少的软件,同时享受许多现代语言特性和一个很赞的社区,那么请关注Rust。
Rust简介系列到此完结,若有后续的系列文章的话,则会侧重该语言的实操和专题详讲。