# Base.Semaphore and @spawn: The Illusion of Control vs. Explicit Resource Management

**URL:** <https://discourse.julialang.org/t/base-semaphore-and-spawn-the-illusion-of-control-vs-explicit-resource-management/136916>\
**Category:** General Usage\
**Created:** [April 29, 2026, 7:47am UTC](https://discourse.julialang.org/t/base-semaphore-and-spawn-the-illusion-of-control-vs-explicit-resource-management/136916 "2026-04-29T07:47:01Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alexander\_B](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alexander_b/32/215374_2.png) [@Alexander\_B](https://discourse.julialang.org/u/Alexander_B)\
**Post date:** [April 29, 2026, 7:47am UTC](https://discourse.julialang.org/t/base-semaphore-and-spawn-the-illusion-of-control-vs-explicit-resource-management/136916/1 "2026-04-29T07:47:01Z")

</div>

All the best to everyone

The Problem  
When using Base.Semaphore to limit the number of concurrently executing heavy tasks, there is a fundamental difference in the behavior of the two approaches:  
Option A (Syntactic sugar do):

```julia-auto
Base.acquire(sem) do
    data = take!(chan)
    @spawn handle(data)
end

```

Option B (Explicit acquire/release via closure) in asynchrony:

```julia-auto
Base.acquire(sem)
data = take!(chan)
@spawn try 
    handle(data)
finally
    Base.release(sem)
end

```

Option A works.

Option B, at least in complex hybrid parallelization schemes, leads to erratic semaphore behavior and stalling.

And I can’t understand whether this is a bug or whether option A is ideologically and/or practically the only correct one?

---

<div class="post-metadata">

**Author:** ![jakobnissen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jakobnissen/32/13477_2.png) [@jakobnissen](https://discourse.julialang.org/u/jakobnissen)\
**Post date:** [April 29, 2026, 2:01pm UTC](https://discourse.julialang.org/t/base-semaphore-and-spawn-the-illusion-of-control-vs-explicit-resource-management/136916/2 "2026-04-29T14:01:26Z")

</div>

In the latter example, the `take!` is outside the try/finally block. So, if `take!` errors, the semaphore is not released.  
Otherwise the two should be identical.

Try moving the `take!` into the try-block. If that doesn’t fix it, can you come up with a minimal working example so we can investigate?

---

<div class="post-metadata">

**Author:** ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)\
**Post date:** [April 29, 2026, 3:46pm UTC](https://discourse.julialang.org/t/base-semaphore-and-spawn-the-illusion-of-control-vs-explicit-resource-management/136916/3 "2026-04-29T15:46:52Z")

</div>

Also depending on the context `data` might be being captured in a closure in the spawn macro in a way you don’t want it to be.  
Ref: [Boxed Variables · OhMyThreads.jl](https://juliafolds2.github.io/OhMyThreads.jl/stable/literate/boxing/boxing/)  
Due to Julia 's scoping rules without the full context it is hard to say if that is the issue here.
