Does EK9 have async/await, goroutines, or manual thread management?
← Concurrency · Ref: Q160
EK9 does not have async/await, goroutines, channels, or manual thread management. Instead, it treats concurrency as a pipeline problem solved with stream operations and MutexLock.
WHAT EK9 DOES NOT HAVE
EK9 deliberately excludes:
- async/await syntax (no colored function problem)
- Goroutines or lightweight coroutines
- Channels or message-passing primitives
- Thread.start() or manual thread creation
- Future/Promise types as first-class constructs
WHY NO ASYNC/AWAIT OR GOROUTINES
async/await creates the 'colored function' problem where async functions cannot be called from sync functions without propagating async throughout the call chain. Goroutines and channels add complexity for coordination. EK9 avoids both by making concurrency a pipeline concern, not a function-level concern.
THE EK9 APPROACH
EK9 provides two concurrency mechanisms:
1. Stream pipelines where the stream type is a zero-arg function delegate and `| async` invokes each element in parallel on virtual threads: `cat workers | async | map with toLine > stdout`. async takes NO function argument — the function IS the stream element.
2. MutexLock of T for protecting shared state, held as a field on a wrapping class so the lock has a stable identity for compile-time data-race and deadlock detection.
These two primitives cover the vast majority of concurrent programming needs.
VIRTUAL THREADS
EK9 runs on Java 25 virtual threads. Virtual threads are extremely lightweight (millions per process) and handle blocking I/O efficiently. The runtime manages scheduling automatically.
COMPILE-TIME SAFETY
The pairing of MutexLock + closed-world call graph + statically-derivable lock identity lets the compiler prove the absence of data races (E08251), lock-order deadlocks (E08252), same-lock-across-thread-boundary issues (E08253), and same-type lock nesting whose acquisition order cannot be statically proven (E08255 — the bank-transfer / dining-philosophers shape) WITHOUT runtime overhead and WITHOUT developer annotations. No other mainstream language does this at compile time.
CONCURRENCY IS A PIPELINE PROBLEM
Most concurrency is about processing items in parallel or protecting shared data. Pipelines handle the first, MutexLock handles the second. No thread pools, no executors, no callback hell.
DESIGN PHILOSOPHY
Like removing break/continue/return, EK9 removes low-level concurrency primitives that cause bugs. Thread safety violations, deadlocks, and race conditions are among the hardest bugs to diagnose. Simpler primitives produce more reliable concurrent programs.
See Q158 for MutexLock (which shows the canonical LockableAddressSet pattern). See Q159 for async pipelines. See Q1298 for lock-order cycle deadlock recovery. See Q1299 for the async + same-lock pitfall. See Q1300 for multi-lock design. See Q89 for stream pipelines. See Q144 for control flow design philosophy.
Example
defines module qa.concurrency.philosophy defines function transform() as pure -> number as Integer <- rtn as String: "processed: " + $number defines program ConcurrencyModelDemo() stdout <- Stdout() // === THE EK9 APPROACH === // EK9 treats concurrency as a pipeline problem: // 1. Stream pipelines for parallel processing items <- List() of Integer items += 1 items += 2 items += 3 cat items | map with transform > stdout // For parallel: cat workers | async | map with toLine > stdout // (stream type IS the function — async takes no parameter) // 2. MutexLock as a field — see Q158 for the canonical // LockableAddressSet pattern. // EK9 has no async/await, no goroutines, no Thread.start(), // no Future. Runs on Java 25 virtual threads. stdout.println("EK9 concurrency: pipelines + MutexLock, no thread management")
Common mistakes
E50060 — EK9 has no .stream() method chains. Use pipe syntax: 'cat items | map with fn > stdout'. Concurrency is a pipeline problem in EK9. See ek9 -h E50060 for details.
Incorrect:
items.stream().map(transform).forEach(stdout)
Correct:
cat items | map with transform > stdout
E50060 — EK9 List has no .add() method. Use the += operator. See ek9 -h E50060 for details.
Incorrect:
items.add(1)
Correct:
items += 1
Other ways to ask this
- Why doesn't EK9 have async/await?
- How is EK9's concurrency model different from Go or Rust?
- Does EK9 support goroutines or channels?
Coming from another language?
Java: CompletableFuture, ExecutorService, synchronized, virtual threads. Python: asyncio with async/await. Rust: async/await with tokio or async-std runtimes. Go: goroutines with channels and select. Kotlin: coroutines with suspend functions. EK9: stream pipelines with async operation and MutexLock, running on Java 25 virtual threads with no explicit thread management.
Keywords: channel, future, design, thread, philosophy, migrate, async, await, concurrency, goroutine, model, parallel, promise