Painting with Threads - Concurrency you can see
This blog covers
- Concurrent programming in Rust
- How to distinguish processes, threads, and containers
- Channels and message passing
- Task queues
- A turtle graphics-inspired SVG generator that draws paths from encoded input strings
This blog is a work in progress and is not complete.
Before I go any further in today's blog let's get some basic things cleared up.
- Processes, threads, and containers are abstractions created to enable multiple tasks to be carried out at the same time. This enables concurrency.
- Its peer term, parallelism, means to make use of multiple physical CPU cores at the same time.
- Counterintuitively, it is possible to have a concurrent system on a single CPU core. Because accessing data from memory and I/O take a long time, threads requesting data can be set to a blocked state. Blocked threads are rescheduled when their data is available.
With these three things out of the way let's get started. Concurrency, or doing multiple things at the same time, is difficult to introduce into a computer program. Employing concurrency effectively involves both new concepts and new syntax.
This will be very beginner friendly guide that aims to make your life easier when you read more complex materials that involve concurrency being used in any shape or form.
Anonymous functions
Now before I start with threads there is yet another topic that I would like to introduce anonymous functions or lambda functions. Their existence is akin to magic for a lot of programmers because they are very helpful in certain situations and a lot of programmers either don't know about them or don't know what to do with them or how to use them.
They are more of functional programming feature and rarely used in classic Object Oriented languages(especially in older codebases since there was no native support for them until Java 8 and C++ 11),
this is how a normal function looks
fn foo(a: i32, b: i32) -> i32 {
a+b
}
the (loosely) equivalent lambda function would look like
let add = |a,b| { a + b };
they are denoted by a pair of vertical bars(| _ |) followed by curly brackets ( { - })
The vertical bars let you define arguments. Lambda functions in rust can read variables from within their scope. These are called closures.
Lambda functions can not be defined in global scope
Spawning threads
Threads enable concurrent execution in modern operating systems, ensuring fair CPU access. Knowing how to create and manage threads is essential for leveraging multi-core processors.
A brief introduction to closures
To spawn a thread in rust e pass an anonymous function to std::threadspawn()
and since it doesn't typically take any arguments this is how it would look like.
thread::spawn(|| {
// --Something--
})