小琳Python课堂继续开讲!今天我们来深入挖掘Python的thread模块中的关键文件,包括thread.cthread_nt.hthread_pthread.h

thread.c:线程功能的中心

  • 功能thread.c是Python线程模块的主要实现文件,包含线程创建、同步、销毁等核心功能的Python C API实现。
  • 跨平台:通过包含特定平台的头文件和调用特定平台的线程API,实现跨平台支持。

thread_nt.h:Windows的专属

  • 平台特定:专为Windows平台设计,包含Windows线程API(如CreateThread、WaitForSingleObject等)的声明和宏定义。
  • 作用:在Windows上,thread.c会包含thread_nt.h来使用Windows的线程API。

thread_pthread.h:POSIX系统的伙伴

  • 平台特定:针对Unix和Unix-like系统,包含POSIX线程(pthread)API的声明和宏定义。
  • 作用:在POSIX兼容系统上,thread.c会包含thread_pthread.h来使用pthread API。

它们之间的关系

  1. 条件包含thread.c根据不同平台包含不同头文件,通过预处理器指令实现。
  2. API调用thread.c中的函数会调用这些头文件中声明的方法。
  3. 平台抽象:提供跨平台线程API,具体线程操作由底层操作系统完成。

实际应用

Python开发者通常通过threading模块使用线程,而不直接与这些底层文件交互。

thread.c的内部揭秘

  • 线程创建:实现_thread.start_new_thread()函数,用于创建新线程。
  • 线程同步:包括锁、条件变量和事件的实现。
  • 线程局部存储:实现线程局部存储(TLS)。
  • 线程销毁:管理线程的退出和资源清理。

实现方式

线程创建
  • 示例代码
static PyObject *
thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
{
    PyObject *func, *args, *keyw = NULL;
    struct bootstate *boot;
    unsigned long ident;
    if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3, &func, &args, &keyw))
        return NULL;
    /* Check whether the thread is already started. */
    if (PyEval_ThreadsInitialized()) {
        // ...
    }
    boot = PyMem_NEW(struct bootstate, 1);
    if (boot == NULL)
        return PyErr_NoMemory();
    boot->interp = PyThreadState_GET()->interp;
    boot->func = func;
    boot->args = args;
    boot->keyw = keyw;
    boot->tstate = _PyThreadState_Prealloc(boot->interp);
    if (boot->tstate == NULL) {
        PyMem_DEL(boot);
        return PyErr_NoMemory();
    }
    /* Create the thread and save its identifier */
    ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
    // ...
}
  • 说明thread_PyThread_start_new_thread函数是Python中创建新线程的接口。它首先解析传入的参数,然后分配一个bootstate结构体来保存线程启动所需的信息,如线程函数、参数等。最后,它调用PyThread_start_new_thread函数(这是一个平台特定的函数,如在POSIX系统上为pthread_create)来创建新线程。
线程同步
  • 示例代码
static PyObject *
thread_PyThread_acquire_lock(PyObject *self, PyObject *args)
{
    int err;
    PyObject *lock, *waitflag, *timeout;
    int wait = 0;
    unsigned long tout = 0;
    if (!PyArg_UnpackTuple(args, "acquire_lock", 2, 3, &lock, &waitflag, &timeout))
        return NULL;
    // ...
    err = PyThread_acquire_lock(lock, wait, tout);
    if (err < 0)
        return NULL;
    // ...
}
  • 说明thread_PyThread_acquire_lock函数用于获取一个锁。它解析传入的参数,然后调用PyThread_acquire_lock函数(这也是一个平台特定的函数)来尝试获取锁。
线程局部存储
  • 示例代码
static PyObject *
thread_PyThread_get_thread_ident(PyObject *self)
{
    return PyLong_FromUnsignedLong((unsigned long)PyThread_get_thread_ident());
}
  • 说明thread_PyThread_get_thread_ident函数用于获取当前线程的标识符。它调用PyThread_get_thread_ident函数(一个平台特定的函数)来获取线程ID,并将其转换为Python对象。
线程销毁
  • 示例代码
static void
t_bootstrap(void *boot_raw)
{
    struct bootstate *boot = (struct bootstate *) boot_raw;
    PyThreadState *tstate;
    PyObject *res;
    tstate = boot->tstate;
    tstate->thread_id = PyThread_get_thread_ident();
    // ...
}
  • 说明t_bootstrap函数是每个新线程的入口点。它负责设置线程状态,并最终执行Python线程函数。线程的退出和资源清理通常由Python的垃圾收集机制和操作系统来处理。

这些代码片段展示了thread.c中一些关键功能的实现方式。要深入了解thread.c的具体内容,建议直接查看Python源代码。你可以在Python的官方网站下载源代码,或者通过版本控制系统(如Git)访问。在源代码中搜索thread.c文件,然后查看其中的函数实现和注释,以了解其详细的工作原理。
今天的分享就到这里,希望对thread模块有了更深的理解!下期见!👋