diff --git a/newsfragments/1638.fix.rst b/newsfragments/1638.fix.rst
new file mode 100644
index 00000000..6c6a9a6a
--- /dev/null
+++ b/newsfragments/1638.fix.rst
@@ -0,0 +1,1 @@
+The thread cache didn't release its reference to the previous job.
diff --git a/trio/_core/_thread_cache.py b/trio/_core/_thread_cache.py
index 8faf5543..ae5e8450 100644
--- a/trio/_core/_thread_cache.py
+++ b/trio/_core/_thread_cache.py
@@ -69,6 +69,8 @@ class WorkerThread:
                 # instead of spawning a new thread.
                 self._thread_cache._idle_workers[self] = None
                 deliver(result)
+                del fn
+                del deliver
             else:
                 # Timeout acquiring lock, so we can probably exit. But,
                 # there's a race condition: we might be assigned a job *just*

to_thread.run_sync() foils meta-class destructors 
Invoking `to_thread.run_sync()` seems to prevent meta-class destructors of completely unrelated classes from being called on shutdown.

```python
import trio

class deltype(type):
    def __del__(self):
        print(f"{self.__name__} class deleted")

Test = deltype("Test", (object,), {})

async def async_main():
    await trio.to_thread.run_sync(lambda: print('hi'))
    await trio.sleep(0)

trio.run(async_main)
```

expected output:
```
hi
Test class deleted
```

actual output:
```
hi
```

if the `run_sync()` is commented out, the meta-class destructor is called as expected:
```
Test class deleted
```

diff --git a/trio/_core/tests/test_thread_cache.py b/trio/_core/tests/test_thread_cache.py
index f19ac1d4..0f6e0a07 100644
--- a/trio/_core/tests/test_thread_cache.py
+++ b/trio/_core/tests/test_thread_cache.py
@@ -4,7 +4,7 @@ from queue import Queue
 import time
 import sys
 
-from .tutil import slow
+from .tutil import slow, gc_collect_harder
 from .. import _thread_cache
 from .._thread_cache import start_thread_soon, ThreadCache
 
@@ -25,6 +25,29 @@ def test_thread_cache_basics():
         outcome.unwrap()
 
 
+def test_thread_cache_deref():
+    res = [False]
+
+    class del_me:
+        def __call__(self):
+            return 42
+
+        def __del__(self):
+            res[0] = True
+
+    q = Queue()
+
+    def deliver(outcome):
+        q.put(outcome)
+
+    start_thread_soon(del_me(), deliver)
+    outcome = q.get()
+    assert outcome.unwrap() == 42
+
+    gc_collect_harder()
+    assert res[0]
+
+
 @slow
 def test_spawning_new_thread_from_deliver_reuses_starting_thread():
     # We know that no-one else is using the thread cache, so if we keep

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
async-generator==1.10
attrs==25.3.0
exceptiongroup==1.2.2
idna==3.10
iniconfig==2.1.0
outcome==1.3.0.post0
packaging==24.2
pluggy==1.5.0
pytest==8.3.5
sniffio==1.3.1
sortedcontainers==2.4.0
tomli==2.2.1
-e git+https://github.com/python-trio/trio.git@e444094a262f69af6a16b60fa59a2ab53316e5ce#egg=trio

name: trio
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - async-generator==1.10
      - attrs==25.3.0
      - exceptiongroup==1.2.2
      - idna==3.10
      - iniconfig==2.1.0
      - outcome==1.3.0.post0
      - packaging==24.2
      - pluggy==1.5.0
      - pytest==8.3.5
      - sniffio==1.3.1
      - sortedcontainers==2.4.0
      - tomli==2.2.1
      - trio==0.16.0+dev
prefix: /opt/conda/envs/trio

trio/_core/tests/test_thread_cache.py::test_thread_cache_deref trio/_core/tests/test_thread_cache.py::test_race_between_idle_exit_and_job_assignment
trio/_core/tests/test_thread_cache.py::test_thread_cache_basics trio/_core/tests/test_thread_cache.py::test_spawning_new_thread_from_deliver_reuses_starting_thread trio/_core/tests/test_thread_cache.py::test_idle_threads_exit
newsfragments/1638.fix.rst trio/_core/_thread_cache.py
newsfragments/1638.fix.rst trio/_core/_thread_cache.py