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*

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

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
```

trio/_core/tests/test_thread_cache.py::test_thread_cache_deref
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