I am a novice programmer interested in the Julia language. The documentation (https://docs.julialang.org/en/v1/base/multi-threading/) says Threads.@threads is for "for" loops and theads.@spawn places a given task on any available thread. My understand is that Threads.@threads is inherently synchronized while the threads.@spawn method is asynchronous and needs more planning to implement (namely using the fetch() method).
In code I find online using both, I seem to see the two used interchangeably (from my perspective). What is the conceptual difference between the two for a novice programmer and how/when should we implement each? Additionally, can they complement each other?
Function std::thread::spawnSpawns a new thread, returning a JoinHandle for it. The join handle provides a join method that can be used to join the spawned thread. If the spawned thread panics, join will return an Err containing the argument given to panic! .
An executing Rust program consists of a collection of native OS threads, each with their own stack and local state. Threads can be named, and provide some built-in support for low-level synchronization.
A thread is a basic unit of CPU utilization, consisting of a program counter, a stack, and a set of registers, ( and a thread ID. ) Traditional ( heavyweight ) processes have a single thread of control - There is one program counter, and one sequence of instructions that can be carried out at any given time.
Threads are not independent of one another like processes are, and as a result threads share with other threads their code section, data section, and OS resources (like open files and signals). But, like process, a thread has its own program counter (PC), register set, and stack space.
Consider:
function withthreads()
arr = zeros(Int, 10)
Threads.@threads for i in 1:10
sleep(3 * rand())
arr[i] = i
end
println("with @threads: $arr")
end
function withspawn()
arr = zeros(Int, 10)
for i in 1:10
Threads.@spawn begin
sleep(3 * rand())
arr[i] = i
end
end
println("with @spawn: $arr")
end
function withsync()
arr = zeros(Int, 10)
@sync begin
for i in 1:10
Threads.@spawn begin
sleep(3 * rand())
arr[i] = i
end
end
end
println("with @sync: $arr")
end
withthreads()
withspawn()
withsync()
output:
with @threads: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
with @spawn: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
with @sync: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
So @threads manages the pool of threads allotted to julia, and spawns up to one thread for each iteration of the for loop (possibly using the same threads more than once for more than one iteration, sequentially as each thread finishes its allotted iteration, if there are more iterations than threads), and also synchonizes the threads, not exiting the for block until all threads have completed. @spawn spawns just one task thread and returns to the main task immediately, and so the block can be exited as soon as all tasks are spawned, even before they are done working (so the zeros remain 0 in array arr).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With