修改静态变量是否安全? [英] Is it thread safe to modify a static variable?

查看:111
本文介绍了修改静态变量是否安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

自C ++ 11起,保证静态变量初始化是线程安全的.但是,如何在多个线程中修改静态变量呢?像下面一样

Since C++11, static variable initialization is guaranteed to be thread safe. But how about modifying a static variable in multiple threads? like below

static int initialized = 0;
Initialize()
{
 if (initialized)
    return;
 initialized = 1; // Is this thread safe? 
}

我问这个问题的原因是我正在阅读源代码 Py_Initialize(),我正在尝试将Python嵌入多线程C ++应用程序中,我想知道在多个线程中多次调用Py_Initialize()是否安全? Py_Initialize()的实现可以归结为 功能_Py_InitializeEx_Private,如下所示

The reason I ask this question is that I am reading the source code for Py_Initialize(), I am trying to embed Python in a multithreaded C++ application, I am wondering if it is safe to call Py_Initialize() multiple times in several threads? The implementation of Py_Initialize() boils down to function _Py_InitializeEx_Private, which is like below

// pylifecycle.c
static int initialized = 0;

_Py_InitializeEx_Private(int install_sigs, int install_importlib)
{
    if (initialized)
        return;
    initialized = 1;
 // a bunch of other stuff
 }

C的结论和C ++一样吗?

And is the conclusion for C the same as C++?

编辑 因此,所有答案都是好的,我选择了最能使我头脑清醒的答案.

EDIT So all the answers are good, I chose the one which clears my head most.

推荐答案

Py_Initialize不是线程安全的.只有知道Python解释器已经初始化,才可以从多个线程调用它,但是如果可以证明调用该函数很愚蠢.

Py_Initialize is not thread-safe. You can call it from multiple threads only if you know that the Python interpreter has already been initialized, but if you can prove that it would be silly to call the function.

实际上,大多数Python C-API调用都不是线程安全的.您需要获取全局解释器锁(GIL)才能与Python解释器进行交互. (请参见 Python C-API文档以获取更多详细信息.请仔细阅读.)

Indeed, most Python C-API calls are not thread-safe; you need to acquire the Global Interpreter Lock (GIL) in order to interact with the Python interpreter. (See the Python C-API docs for more details. Read it carefully.)

但是,据我所知,在初始化解释器之前,您无法使用标准API来获取GIL.因此,如果您有多个线程,其中任何一个线程都可能初始化相同的Python解释器,则需要使用自己的互斥锁来保护对Py_Initialize的调用.如果可能使用程序逻辑,那么在启动任何线程之前最好进行一次初始化.

However, as far as I know you cannot use the standard API to acquire the GIL until the interpreter has been initialized. So if you have multiple threads, any of which might initialize the same Python interpreter, you would need to protect the calls to Py_Initialize with your own mutex. You might well be better off doing the initialization once before you start up any threads, if that is possible with your program logic.

您引用的代码:

static int initialized = 0;

void Initialize_If_Necessary() 
{
    if (initialized)
        return;
    initialized = 1;
    // Do the initialization only once
}

即使initialized是原子类型,

显然也不是任何语言的线程安全.假设有两个线程在任何初始化发生之前同时执行此代码:它们都将initialized视为false,因此它们都进行了初始化. (如果没有两个核心,您可以想象第一个过程是在initialized的测试和分配之间进行任务切换.)

is clearly not threadsafe in any language, even if initialized is an atomic type. Suppose two threads were simultaneously executing this code before any initialization happened: both of them see initialized as false, so both of them proceed with the initialization. (If you don't have two cores, you could imagine that the first process is task switched between the test of initialized and the assignment.)

这篇关于修改静态变量是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆