同步原始物件

The C-API provides a basic mutual exclusion lock.

typePyMutex

A mutual exclusion lock. ThePyMutex should be initialized tozero to represent the unlocked state. For example:

PyMutexmutex={0};

Instances ofPyMutex should not be copied or moved. Both thecontents and address of aPyMutex are meaningful, and it mustremain at a fixed, writable location in memory.

備註

APyMutex currently occupies one byte, but the size should beconsidered unstable. The size may change in future Python releaseswithout a deprecation period.

在 3.13 版被加入.

voidPyMutex_Lock(PyMutex*m)

Lock mutexm. If another thread has already locked it, the callingthread will block until the mutex is unlocked. While blocked, the threadwill temporarily detach thethread state if one exists.

在 3.13 版被加入.

voidPyMutex_Unlock(PyMutex*m)

Unlock mutexm. The mutex must be locked --- otherwise, the function willissue a fatal error.

在 3.13 版被加入.

intPyMutex_IsLocked(PyMutex*m)

Returns non-zero if the mutexm is currently locked, zero otherwise.

備註

This function is intended for use in assertions and debugging only andshould not be used to make concurrency control decisions, as the lockstate may change immediately after the check.

在 3.14 版被加入.

Python critical section API

The critical section API provides a deadlock avoidance layer on top ofper-object locks forfree-threaded CPython. They areintended to replace reliance on theglobal interpreter lock, and areno-ops in versions of Python with the global interpreter lock.

Critical sections are intended to be used for custom types implementedin C-API extensions. They should generally not be used with built-in types likelist anddict because their public C-APIsalready use critical sections internally, with the notableexception ofPyDict_Next(), which requires critical sectionto be acquired externally.

Critical sections avoid deadlocks by implicitly suspending active criticalsections, hence, they do not provide exclusive access such as provided bytraditional locks likePyMutex. When a critical section is started,the per-object lock for the object is acquired. If the code executed inside thecritical section calls C-API functions then it can suspend the critical section therebyreleasing the per-object lock, so other threads can acquire the per-object lockfor the same object.

Variants that acceptPyMutex pointers rather than Python objects are alsoavailable. Use these variants to start a critical section in a situation wherethere is noPyObject -- for example, when working with a C type thatdoes not extend or wrapPyObject but still needs to call into the CAPI in a manner that might lead to deadlocks.

The functions and structs used by the macros are exposed for caseswhere C macros are not available. They should only be used as in thegiven macro expansions. Note that the sizes and contents of the structures maychange in future Python versions.

備註

Operations that need to lock two objects at once must usePy_BEGIN_CRITICAL_SECTION2. Youcannot use nested criticalsections to lock more than one object at once, because the inner criticalsection may suspend the outer critical sections. This API does not providea way to lock more than two objects at once.

範例用法:

staticPyObject*set_field(MyObject*self,PyObject*value){Py_BEGIN_CRITICAL_SECTION(self);Py_SETREF(self->field,Py_XNewRef(value));Py_END_CRITICAL_SECTION();Py_RETURN_NONE;}

In the above example,Py_SETREF callsPy_DECREF, whichcan call arbitrary code through an object's deallocation function. The criticalsection API avoids potential deadlocks due to reentrancy and lock orderingby allowing the runtime to temporarily suspend the critical section if thecode triggered by the finalizer blocks and callsPyEval_SaveThread().

Py_BEGIN_CRITICAL_SECTION(op)

Acquires the per-object lock for the objectop and begins acritical section.

In the free-threaded build, this macro expands to:

{PyCriticalSection_py_cs;PyCriticalSection_Begin(&_py_cs,(PyObject*)(op))

In the default build, this macro expands to{.

在 3.13 版被加入.

Py_BEGIN_CRITICAL_SECTION_MUTEX(m)

Locks the mutexm and begins a critical section.

In the free-threaded build, this macro expands to:

{PyCriticalSection_py_cs;PyCriticalSection_BeginMutex(&_py_cs,m)

Note that unlikePy_BEGIN_CRITICAL_SECTION, there is no cast forthe argument of the macro - it must be aPyMutex pointer.

On the default build, this macro expands to{.

在 3.14 版被加入.

Py_END_CRITICAL_SECTION()

Ends the critical section and releases the per-object lock.

In the free-threaded build, this macro expands to:

PyCriticalSection_End(&_py_cs);}

In the default build, this macro expands to}.

在 3.13 版被加入.

Py_BEGIN_CRITICAL_SECTION2(a,b)

Acquires the per-object locks for the objectsa andb and begins acritical section. The locks are acquired in a consistent order (lowestaddress first) to avoid lock ordering deadlocks.

In the free-threaded build, this macro expands to:

{PyCriticalSection2_py_cs2;PyCriticalSection2_Begin(&_py_cs2,(PyObject*)(a),(PyObject*)(b))

In the default build, this macro expands to{.

在 3.13 版被加入.

Py_BEGIN_CRITICAL_SECTION2_MUTEX(m1,m2)

Locks the mutexesm1 andm2 and begins a critical section.

In the free-threaded build, this macro expands to:

{PyCriticalSection2_py_cs2;PyCriticalSection2_BeginMutex(&_py_cs2,m1,m2)

Note that unlikePy_BEGIN_CRITICAL_SECTION2, there is no cast forthe arguments of the macro - they must bePyMutex pointers.

On the default build, this macro expands to{.

在 3.14 版被加入.

Py_END_CRITICAL_SECTION2()

Ends the critical section and releases the per-object locks.

In the free-threaded build, this macro expands to:

PyCriticalSection2_End(&_py_cs2);}

In the default build, this macro expands to}.

在 3.13 版被加入.

Legacy locking APIs

These APIs are obsolete since Python 3.13 with the introduction ofPyMutex.

typePyThread_type_lock

A pointer to a mutual exclusion lock.

typePyLockStatus

The result of acquiring a lock with a timeout.

enumeratorPY_LOCK_FAILURE

Failed to acquire the lock.

enumeratorPY_LOCK_ACQUIRED

The lock was successfully acquired.

enumeratorPY_LOCK_INTR

The lock was interrupted by a signal.

PyThread_type_lockPyThread_allocate_lock(void)
穩定 ABI 的一部分.

Allocate a new lock.

On success, this function returns a lock; on failure, thisfunction returns0 without an exception set.

呼叫者不需擁有一個attached thread state

voidPyThread_free_lock(PyThread_type_locklock)
穩定 ABI 的一部分.

Destroylock. The lock should not be held by any thread when callingthis.

呼叫者不需擁有一個attached thread state

PyLockStatusPyThread_acquire_lock_timed(PyThread_type_locklock,longlongmicroseconds,intintr_flag)
穩定 ABI 的一部分.

Acquirelock with a timeout.

This will wait formicroseconds microseconds to acquire the lock. If thetimeout expires, this function returnsPY_LOCK_FAILURE.Ifmicroseconds is-1, this will wait indefinitely until the lock hasbeen released.

Ifintr_flag is1, acquiring the lock may be interrupted by a signal,in which case this function returnsPY_LOCK_INTR. Uponinterruption, it's generally expected that the caller makes a call toPy_MakePendingCalls() to propagate an exception to Python code.

If the lock is successfully acquired, this function returnsPY_LOCK_ACQUIRED.

呼叫者不需擁有一個attached thread state

intPyThread_acquire_lock(PyThread_type_locklock,intwaitflag)
穩定 ABI 的一部分.

Acquirelock.

Ifwaitflag is1 and another thread currently holds the lock, thisfunction will wait until the lock can be acquired and will always return1.

Ifwaitflag is0 and another thread holds the lock, this function willnot wait and instead return0. If the lock is not held by any otherthread, then this function will acquire it and return1.

UnlikePyThread_acquire_lock_timed(), acquiring the lock cannot beinterrupted by a signal.

呼叫者不需擁有一個attached thread state

intPyThread_release_lock(PyThread_type_locklock)
穩定 ABI 的一部分.

Releaselock. Iflock is not held, then this function issues afatal error.

呼叫者不需擁有一個attached thread state