Concurrency
Concurrency lives in the thread module. It is VM-based: each spawned
function runs in its own isolated VM with a copy of the current globals. That
isolation is what keeps concurrent work safe — tasks don’t share mutable state
unless you opt in through the runtime store.
import thread
Spawning goroutines
import thread
thread.core.spawn(fn() {
println("running in the background")
})
Other thread.core helpers: sleep(ms), cpus(), goroutines().
Async futures
Run work and await its result:
import thread
import time
let future = thread.async.run(fn() {
time.timer.sleep(100)
return "done"
})
println(thread.async.await(future)) // "done"
Channels
Typed message passing between tasks:
import thread
let ch = thread.channel.new(10) // buffered channel, capacity 10
thread.core.spawn(fn() {
thread.channel.send(ch, "hello from goroutine")
})
let msg = thread.channel.recv(ch)
println(msg)
Channel functions: new(capacity), send, recv, recvTimeout(id, ms),
close, len, cap.
Locks & primitives
The thread module also provides the usual primitives:
| Sub-module | Purpose |
|---|---|
thread.mutex | Mutual-exclusion lock (lock, unlock, tryLock) |
thread.rwlock | Reader/writer lock |
thread.semaphore | Bounded concurrency (acquire, release) |
thread.atomic | Atomic integer (load, store, add, cas) |
thread.pool | Worker pool (submit, wait) |
thread.scheduler | Run a set of functions in sequence |
import thread
let mu = thread.mutex.new()
fn safeIncrement() {
thread.mutex.lock(mu)
// ... modify shared state ...
thread.mutex.unlock(mu)
}
Sharing state across VMs
Because spawned tasks (and HTTP requests) run in isolated VMs, share data
through the global store in runtime.core:
import runtime
import thread
runtime.core.share("counter", "0")
fn worker() {
let val = toInt(runtime.core.fetch("counter"))
runtime.core.share("counter", toString(val + 1))
}
thread.core.spawn(worker)
thread.core.spawn(worker)
Guard read-modify-write sequences with a thread.mutex when correctness under
contention matters.