Đồng bộ hóa nguyên thủy¶
C-API cung cấp khóa loại trừ lẫn nhau cơ bản.
-
type PyMutex¶
Một khóa loại trừ lẫn nhau. Zz000zz phải được khởi tạo về 0 để thể hiện trạng thái đã mở khóa. Ví dụ:
PyMutex mutex = {0};
Không nên sao chép hoặc di chuyển các phiên bản
PyMutex. Cả nội dung và địa chỉ củaPyMutexđều có ý nghĩa và nó phải ở một vị trí cố định, có thể ghi trong bộ nhớ.Ghi chú
Một
PyMutexhiện chiếm một byte nhưng kích thước được coi là không ổn định. Kích thước có thể thay đổi trong các bản phát hành Python trong tương lai mà không có thời gian ngừng sử dụng.Added in version 3.13.
-
void PyMutex_Lock(PyMutex *m)¶
- Thread safety: Atomic.
Khóa mutex m. Nếu một luồng khác đã khóa nó thì luồng gọi sẽ chặn cho đến khi mutex được mở khóa. Trong khi bị chặn, chuỗi sẽ tạm thời tách thread state nếu có.
Added in version 3.13.
-
void PyMutex_Unlock(PyMutex *m)¶
- Thread safety: Atomic.
Mở khóa mutex m. Mutex phải được khóa --- nếu không hàm sẽ gây ra lỗi nghiêm trọng.
Added in version 3.13.
-
int PyMutex_IsLocked(PyMutex *m)¶
- Thread safety: Atomic.
Trả về khác 0 nếu mutex m hiện bị khóa, nếu không thì trả về 0.
Ghi chú
Chức năng này chỉ nhằm mục đích sử dụng trong xác nhận và gỡ lỗi và không nên sử dụng để đưa ra quyết định kiểm soát đồng thời vì trạng thái khóa có thể thay đổi ngay sau khi kiểm tra.
Added in version 3.14.
Phần quan trọng của Python API¶
Phần quan trọng API cung cấp lớp tránh bế tắc bên trên các khóa cho mỗi đối tượng cho free-threaded CPython. Chúng nhằm mục đích thay thế sự phụ thuộc vào global interpreter lock và không hoạt động trong các phiên bản Python có khóa trình thông dịch toàn cầu.
Các phần quan trọng nhằm mục đích sử dụng cho các loại tùy chỉnh được triển khai trong tiện ích mở rộng C-API. Nói chung, chúng không nên được sử dụng với các loại tích hợp sẵn như list và dict vì các C-API công khai của chúng đã sử dụng các phần quan trọng trong nội bộ, ngoại trừ đáng chú ý là PyDict_Next(), yêu cầu phần quan trọng phải được lấy từ bên ngoài.
Các phần quan trọng tránh bế tắc bằng cách tạm dừng ngầm các phần quan trọng đang hoạt động, do đó, chúng không cung cấp quyền truy cập độc quyền như các khóa truyền thống như PyMutex cung cấp. Khi một phần quan trọng được bắt đầu, khóa mỗi đối tượng cho đối tượng đó sẽ được lấy. Nếu mã được thực thi bên trong phần quan trọng gọi các hàm C-API thì mã có thể tạm dừng phần quan trọng do đó giải phóng khóa theo đối tượng, do đó các luồng khác có thể lấy khóa theo đối tượng cho cùng một đối tượng.
Các biến thể chấp nhận con trỏ PyMutex thay vì đối tượng Python cũng có sẵn. Sử dụng các biến thể này để bắt đầu một phần quan trọng trong tình huống không có PyObject -- ví dụ: khi làm việc với loại C không mở rộng hoặc bao bọc PyObject nhưng vẫn cần gọi vào C API theo cách có thể dẫn đến bế tắc.
Các hàm và cấu trúc được macro sử dụng sẽ được hiển thị trong trường hợp macro C không có sẵn. Chúng chỉ nên được sử dụng như trong các phần mở rộng macro nhất định. Lưu ý rằng kích thước và nội dung của cấu trúc có thể thay đổi trong các phiên bản Python trong tương lai.
Ghi chú
Các thao tác cần khóa 2 đối tượng cùng lúc phải sử dụng Py_BEGIN_CRITICAL_SECTION2. Bạn cannot sử dụng các phần quan trọng lồng nhau để khóa nhiều đối tượng cùng một lúc, vì phần quan trọng bên trong có thể tạm dừng các phần quan trọng bên ngoài. Zz002zz này không cung cấp cách khóa nhiều hơn hai đối tượng cùng một lúc.
Ví dụ sử dụng:
PyObject tĩnh *
set_field(MyObject *self, PyObject *value)
{
Py_BEGIN_CRITICAL_SECTION(tự);
Py_SETREF(self->field, Py_XNewRef(value));
Py_END_CRITICAL_SECTION();
Py_RETURN_NONE;
}
Trong ví dụ trên, Py_SETREF gọi Py_DECREF, có thể gọi mã tùy ý thông qua chức năng phân bổ của đối tượng. Phần quan trọng API tránh được tình trạng bế tắc tiềm ẩn do truy cập lại và thứ tự khóa bằng cách cho phép bộ thực thi tạm thời tạm dừng phần quan trọng nếu mã được trình hoàn thiện chặn và gọi PyEval_SaveThread().
-
Py_BEGIN_CRITICAL_SECTION(op)¶
Nhận khóa theo đối tượng cho đối tượng op và bắt đầu một phần quan trọng.
Trong bản dựng có luồng tự do, macro này mở rộng thành:
{ PyCriticalSection _py_cs; PyCriticalSection_Begin(&_py_cs, (PyObject*)(op))
Trong bản dựng mặc định, macro này mở rộng thành
{.Added in version 3.13.
-
Py_BEGIN_CRITICAL_SECTION_MUTEX(m)¶
Khóa mutex m và bắt đầu một phần quan trọng.
Trong bản dựng có luồng tự do, macro này mở rộng thành:
{ PyCriticalSection _py_cs; PyCriticalSection_BeginMutex(&_py_cs, m)
Lưu ý rằng không giống như
Py_BEGIN_CRITICAL_SECTION, không có kiểu truyền nào cho đối số của macro - nó phải là con trỏPyMutex.Trên bản dựng mặc định, macro này mở rộng thành
{.Added in version 3.14.
-
Py_END_CRITICAL_SECTION()¶
Kết thúc phần quan trọng và giải phóng khóa theo từng đối tượng.
Trong bản dựng có luồng tự do, macro này mở rộng thành:
PyCriticalSection_End(&_py_cs); }
Trong bản dựng mặc định, macro này mở rộng thành
}.Added in version 3.13.
-
Py_BEGIN_CRITICAL_SECTION2(a, b)¶
Nhận khóa theo từng đối tượng cho các đối tượng a và b và bắt đầu một phần quan trọng. Các khóa được lấy theo thứ tự nhất quán (địa chỉ thấp nhất trước) để tránh tình trạng bế tắc về thứ tự khóa.
Trong bản dựng có luồng tự do, macro này mở rộng thành:
{ PyCriticalSection2 _py_cs2; PyCriticalSection2_Begin(&_py_cs2, (PyObject*)(a), (PyObject*)(b))
Trong bản dựng mặc định, macro này mở rộng thành
{.Added in version 3.13.
-
Py_BEGIN_CRITICAL_SECTION2_MUTEX(m1, m2)¶
Khóa các mutex m1 và m2 và bắt đầu một phần quan trọng.
Trong bản dựng có luồng tự do, macro này mở rộng thành:
{ PyCriticalSection2 _py_cs2; PyCriticalSection2_BeginMutex(&_py_cs2, m1, m2)
Lưu ý rằng không giống như
Py_BEGIN_CRITICAL_SECTION2, không có kiểu truyền nào cho các đối số của macro - chúng phải là con trỏPyMutex.Trên bản dựng mặc định, macro này mở rộng thành
{.Added in version 3.14.
-
Py_END_CRITICAL_SECTION2()¶
Kết thúc phần quan trọng và giải phóng các khóa cho mỗi đối tượng.
Trong bản dựng có luồng tự do, macro này mở rộng thành:
PyCriticalSection2_End(&_py_cs2); }
Trong bản dựng mặc định, macro này mở rộng thành
}.Added in version 3.13.
API khóa kế thừa¶
Các API này đã lỗi thời kể từ Python 3.13 với sự ra đời của PyMutex.
-
type PyThread_type_lock¶
Một con trỏ tới khóa loại trừ lẫn nhau.
-
type PyLockStatus¶
Kết quả của việc có được một khóa có thời gian chờ.
-
enumerator PY_LOCK_FAILURE¶
Không lấy được khóa.
-
enumerator PY_LOCK_ACQUIRED¶
Khóa đã được lấy thành công.
-
enumerator PY_LOCK_INTR¶
Khóa bị gián đoạn bởi một tín hiệu.
-
enumerator PY_LOCK_FAILURE¶
-
PyThread_type_lock PyThread_allocate_lock(void)¶
- Một phần của ABI ổn định.
Phân bổ một khóa mới.
Khi thành công, hàm này trả về một khóa; nếu thất bại, hàm này trả về
0mà không đặt ngoại lệ.Người gọi không cần giữ attached thread state.
-
void PyThread_free_lock(PyThread_type_lock lock)¶
- Một phần của ABI ổn định.
Tiêu diệt lock. Khóa không được giữ bởi bất kỳ luồng nào khi gọi nó.
Người gọi không cần giữ attached thread state.
-
PyLockStatus PyThread_acquire_lock_timed(PyThread_type_lock lock, long long microseconds, int intr_flag)¶
- Một phần của ABI ổn định.
Có được lock khi hết thời gian chờ.
Điều này sẽ đợi microseconds micro giây để lấy khóa. Nếu hết thời gian chờ, hàm này trả về
PY_LOCK_FAILURE. Nếu microseconds là-1, thao tác này sẽ đợi vô thời hạn cho đến khi khóa được giải phóng.Nếu intr_flag là
1, việc lấy khóa có thể bị gián đoạn bởi tín hiệu, trong trường hợp đó hàm này trả vềPY_LOCK_INTR. Khi bị gián đoạn, thông thường người gọi sẽ thực hiện lệnh gọi tớiPy_MakePendingCalls()để truyền một ngoại lệ cho mã Python.Nếu khóa được lấy thành công, hàm này trả về
PY_LOCK_ACQUIRED.Người gọi không cần giữ attached thread state.
-
int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)¶
- Một phần của ABI ổn định.
Mua lock.
Nếu waitflag là
1và một luồng khác hiện đang giữ khóa, chức năng này sẽ đợi cho đến khi có thể lấy được khóa và sẽ luôn trả về1.Nếu waitflag là
0và một luồng khác giữ khóa, hàm này sẽ không chờ và thay vào đó trả về0. Nếu khóa không được giữ bởi bất kỳ luồng nào khác thì hàm này sẽ lấy nó và trả về1.Không giống như
PyThread_acquire_lock_timed(), việc lấy khóa không thể bị gián đoạn bởi tín hiệu.Người gọi không cần giữ attached thread state.
-
int PyThread_release_lock(PyThread_type_lock lock)¶
- Một phần của ABI ổn định.
Phát hành lock. Nếu lock không được giữ thì chức năng này sẽ gây ra lỗi nghiêm trọng.
Người gọi không cần giữ attached thread state.