[go: up one dir, main page]

0% found this document useful (0 votes)
10 views42 pages

L10-Safety in Rust

The document discusses the challenges of concurrent programming and introduces Rust as a solution that emphasizes safety through ownership and borrowing, preventing issues like data races and memory safety violations. It covers Rust's concurrency features, including threads, Mutex, and libraries like Crossbeam and Rayon, which facilitate safe concurrent programming. The document highlights Rust's strong safety guarantees and performance, making it suitable for confident systems programming.

Uploaded by

Chang Jingyan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views42 pages

L10-Safety in Rust

The document discusses the challenges of concurrent programming and introduces Rust as a solution that emphasizes safety through ownership and borrowing, preventing issues like data races and memory safety violations. It covers Rust's concurrency features, including threads, Mutex, and libraries like Crossbeam and Rayon, which facilitate safe concurrent programming. The document highlights Rust's strong safety guarantees and performance, making it suitable for confident systems programming.

Uploaded by

Chang Jingyan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 42

Safety in Concurrent

Programming with Rust


CS3211 Parallel and Concurrent Programming
Outline
• Challenges in concurrent programming
• Introducing Rust
• Safety, ownership and borrowing
• Concurrency in Rust
• Threads, Mutex, Atomic
• Libraries: Crossbeam, Rayon

CS3211 L10 - Safety in Rust 2


Challenges in concurrent programming
• Parallelizing … anything is a daunting task
• The goal is to make things faster
• Many times, parallelizing is done by just adding another instance that does
the same work
• Race conditions, data races, deadlocks, starvation
• Unsafe usage of memory in C/C++
• Use after free (UAF)
• Double free

CS3211 L10 - Safety in Rust 3


Fearless Concurrency in Rust
• Rust was initiated with two goals in mind:
• Safety in systems programming
• Painless concurrency

CS3211 L10 - Safety in Rust 4


Rust nowadays
• Strong safety guarantees
• No seg-faults, no data races, expressive type system
• Without compromising on performance
• No garbage collector, no runtime
• Same level of performance as C/C++
• Goal
• Confident, productive systems programming

CS3211 L10 - Safety in Rust 5


C++ is unsafe
• Vector is freed when we exit the scope

CS3211 L10 - Safety in Rust 6


C++ is unsafe
• Dangling pointers issues

CS3211 L10 - Safety in Rust 7


C++ is unsafe
• Aliased pointers – pointers that point
to the same chunk of memory
• elem and vector[0]
• Mutation – changing a pointer
• Aliasing + mutation – changing
(modifying) pointers that point to the
same chunk of memory

CS3211 L10 - Safety in Rust 8


Solution
• Ownership and borrowing
• Prevent simultaneous mutation and aliasing
• No runtime like in C++
• Memory safety like in garbage-collected languages
• No data races like in …Rust

CS3211 L10 - Safety in Rust 9


Ownership (1)
• Lines 2-4:
• Vector book is initialized
• Owner: main function

CS3211 L10 - Safety in Rust 10


Ownership (2)
• Line 5: give ownership to publish
• Pass the without &
• Runtime
• Copy over the fields from main’s stack
to publish’s stack
• Forget about the first book in main
• Line 12: runs the destructor for
book

CS3211 L10 - Safety in Rust 11


Ownership (3)
• Line 5: give ownership to publish
• Line 8: compilation error
• Error: use of moved value book

Ownership does not allow aliasing!

CS3211 L10 - Safety in Rust 12


Rust ownership compared to C++
• Rust: giving ownership is the default
• Not like the copy constructor in C++
• A bit like a move in C++, but enforced at compilation time and no ownership is
retained
• Rust: deep copy of data is explicit using clone()
• In C++, the copy constructor does a deep copy

CS3211 L10 - Safety in Rust 13


Immutable borrow
(Shared borrow)
• Line 12: type is a reference to a
vector –> use &
• Line 5, 10: borrow the vector,
creating an immutable (shared)
reference

A shared borrow allows aliasing, but no mutation!

CS3211 L10 - Safety in Rust 14


Consequences of immutable borrow
• Line 4: vector is (shared) borrowed here
• Freezes the whole container vector
• Line 9: cannot mutate (compilation error)

A shared borrow allows aliasing, but no mutation!

CS3211 L10 - Safety in Rust 15


Mutable borrow
• Line 9: mutable reference to a vector
• Line 5, 6: 2 successful mutable borrows

CS3211 L10 - Safety in Rust 16


Shared borrow: “Don’t break your friend’s toys”

A shared borrow allows aliasing, but no mutation!

CS3211 L10 - Safety in Rust 17


Mutable borrow: “No, it’s my turn now!”

A mutable borrow allows mutation, but no aliasing!

CS3211 L10 - Safety in Rust 18


Memory safety in Rust
• The borrow checker statically prevents aliasing + mutation
• Compile time
• Fighting the borrow checker!
• Don’t give up! Don’t use unsafe!
• Ownership prevents double-free
• The owner frees
• Borrowing prevents use-after-free

• No segfaults! Type Ownership Alias? Mutate?


T Owned Yes
&T Shared reference Yes
&mut T Mutable reference Yes
CS3211 L10 - Safety in Rust 19
No data races in Rust
• Data race = sharing + mutation + no ordering
• Sharing + mutation are prevented in Rust

CS3211 L10 - Safety in Rust 20


Library-based concurrency
• Not build into the language
• Rust had message passing build into the language – removed
• Library-based – in std or other libraries
• Multi-paradigm
• Leverage on ownership/borrowing

CS3211 L10 - Safety in Rust 21


Rust tools
• Rustup – to install your rust tools
• Rustc – the Rust compiler
• Cargo
• Calls the compiler – rustc
• TOML (Tom’s Obvious, Minimal Language) format for the configuration file
• Packages, crates, modules
• A package is one or more crates that provide a set of functionality
• A crate is a binary or library
• Modules are used to organize code within a crate into groups
• Privacy control

CS3211 L10 - Safety in Rust 22


Create a thread
• Line 1: create a thread
• loc is a JoinHandle
• If loc is dropped, the spawned thread is detached
• Line 5: join a thread

CS3211 L10 - Safety in Rust 23


Transfer the vector to a thread
• move converts any variables
captured by reference or mutable
reference to variables captured by
value
• move keyword: the closure will take
ownership of the values it uses from
the environment, thus transferring
ownership of those values from one
thread to another
• Line 5: error:
use after move

CS3211 L10 - Safety in Rust 24


Remove the move
• Line 3: error: value doesn’t live long enough
• Possible memory issues: UAF

• Spawn a thread
• Capture everything as a borrow
• The closure captures dst (mutable borrow)
• Rust infers how to capture dst

CS3211 L10 - Safety in Rust 25


Reference counted type (RC)

• Line 4: error: Rc<T> can’t be


sent across threads
• RC type is not atomically
managed
• No Send trait

CS3211 L10 - Safety in Rust 26


Traits
• Like an interface that you can implement for a given type
• It might have methods
• Example
• Clone
• Marker traits:
• Send – transferred across thread boundaries
• String, u32, Arc<String>
• Sync – safe to share references between threads
• Type T is Sync if and only if &T is Send
• Copy – safe to memcpy (for built-in types)
• u32, f32
• Not for Strings

CS3211 L10 - Safety in Rust 27


Atomic Reference Counted - Arc
• Arc: allows only shared references
• References cannot be mutated
• Line 3: move reference v (but the vector is a shared reference)
• Line 4: it’s safe to access v, but the vector cannot be modified

CS3211 L10 - Safety in Rust 28


Synchronization in Rust
• Shared memory
• Mutex
• Atomics
• Message-passing
• Channels: MPSC (multi-producer, single-consumer FIFO queue)

CS3211 L10 - Safety in Rust 29


Mutex • Based on ownership
• Data protected by the mutex
• Lock returns a guard - a proxy through which we can access the data

CS3211 L10 - Safety in Rust 30


Atomics
• Similar to modern C++
• Same memory model
• Ordering of memory operations – SeqCst, Relaxed, etc.
• Line 1: number is not mutable
• We mutate this through a shared reference
• Access the shared references through some ordering (memory model)

CS3211 L10 - Safety in Rust 31


Multi-Producer, Single-Consumer FIFO queue
• Channel with a reading and writing reference
• In the example: one reader and multiple writers
• Single consumer: we can’t clone the reading end of the channel

CS3211 L10 - Safety in Rust 32


Outline
• Challenges in concurrent programming
• Introducing Rust
• Safety, ownership and borrowing
• Concurrency in Rust
• Threads, Mutex, Atomic
• Libraries: Crossbeam, Rayon

CS3211 L10 - Safety in Rust 33


Crossbeam
• Ability to create scoped threads – now in std
• Scope is like a little container we are going to put our threads in
• You cannot borrow variables mutably into two threads in the same scope
• Message passing using multiple-producer-multiple-consumer channel
• With exponential backoff

CS3211 L10 - Safety in Rust 34


Scoped threads
• Line 5: create the scope
• Line 6: spawn threads

CS3211 L10 - Safety in Rust 35


Producer consumer
• Line 12: use a bounded channel

CS3211 L10 - Safety in Rust 36


Exponential backoff
• Resources might not be available right now?
• Retry later
• It’s unhelpful to have a tight loop that simply retries as fast as
possible
• Wait a little bit and try again
• If the error occurs, next time wait a little longer
• Rationale: if the resource is overloaded right now, the reaction of
requesting it more will make it even more overloaded and makes the
problem worse!

CS3211 L10 - Safety in Rust 37


Backoff with scoped threads
• Line 12: backoff in lock-free loop
• Line 20: wait for another thread to take its turn first

CS3211 L10 - Safety in Rust 38


Rayon
• A data parallelism library
• Parallelize some spots without full/major rewrite
• Similar in functionality with OpenMP
• But OpenMP uses compiler directives
• Rationale: reasonably common that computationally-intensive parts
of the program happen in a loop, so parallelizing loops is likely to be
quite profitable

CS3211 L10 - Safety in Rust 39


Example: Sequential maximum of a vector

CS3211 L10 - Safety in Rust 40


Example: Maximum of a vector with Rayon

CS3211 L10 - Safety in Rust 41


Rust in a nutshell
• Zero-cost abstraction (like C/C++)
• Memory safety & data-race freedom
• Results in
• Confident, productive systems programming

• References:
• https://www.youtube.com/watch?v=SiUBdUE7xnA
• https://www.youtube.com/watch?v=L0dEE2IqbD8
• https://www.youtube.com/watch?v=6BYKw0Y758Q

CS3211 L10 - Safety in Rust 43

You might also like