Add a thread-owned (thread-aware) non-reentrant lock to threading (only owner can release)

Inspired by threading.Condition._is_owned() is wrong when using threading.Lock · Issue #69702 · python/cpython · GitHub, I think python doesn’t have a thread-owned non-reentrant lock that will be more and more useful when python enters into a free-threading era.

Current workaround is to use RLock, and that forces re-entrancy whether you want it or not.

What I’m suggesting is a small addition, not a behavior change, we can call it OwnedLock:

lock = threading.OwnedLock()

Semantics:

  • non-reentrant (like Lock)

  • thread-owned (like RLock)

  • calling release() from a non-owner thread raises

And we can rewrite RLock to use OwnedLock internally with a level, it looks like the following in c code

typedef struct {
    PyMutex mutex;
    unsigned long long thread;  // i.e., PyThread_get_thread_ident_ex()
} PyOwnedMutex

typedef struct {
    PyOwnedMutex mutex;
    size_t level;
} _PyRecursiveMutex;