Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从多个线程写入静态数据实际上安全吗_C++_Multithreading - Fatal编程技术网

C++ 从多个线程写入静态数据实际上安全吗

C++ 从多个线程写入静态数据实际上安全吗,c++,multithreading,C++,Multithreading,我想从数据库中缓存一些状态数据。多个线程中的任何一个都可以修改状态数据。数据修改后将写入数据库。数据库写入总是由底层数据库访问层串联完成,它在不同的进程中对数据库操作进行排队,因此我不关心这些操作的竞争条件 仅仅修改几个线程中的静态数据是否有问题?从理论上讲,修改可能以读、修改、写的方式实现,但在实践中,我无法想象会是这样 我的数据处理类将如下所示: class StatusCache { public: static void SetActivityStarted(bool activ

我想从数据库中缓存一些状态数据。多个线程中的任何一个都可以修改状态数据。数据修改后将写入数据库。数据库写入总是由底层数据库访问层串联完成,它在不同的进程中对数据库操作进行排队,因此我不关心这些操作的竞争条件

仅仅修改几个线程中的静态数据是否有问题?从理论上讲,修改可能以读、修改、写的方式实现,但在实践中,我无法想象会是这样

我的数据处理类将如下所示:

class StatusCache
{
public:
    static void SetActivityStarted(bool activityStarted)
        { m_activityStarted = activityStarted; WriteToDB(); }
    static void SetActivityComplete(bool activityComplete);
        { m_activityComplete = activityComplete; WriteToDB(); }
    static void SetProcessReady(bool processReady);
        { m_processReady = processReady; WriteToDB(); }
    static void SetProcessPending(bool processPending);
        { m_processPending = processPending; WriteToDB(); }
private:
    static void WriteToDB(); // will write all the class data to the db (multiple requests will happen in series)
    static bool m_activityStarted;
    static bool m_activityComplete;
    static bool m_processReady;
    static bool m_processPending;
};
我不想使用锁,因为在应用程序的这一部分已经有几个锁,添加更多的锁会增加死锁的可能性

在数据库更新中,两个线程之间是否有重叠并不重要,例如

thread 1                        thread 2                    activity started in db
SetActivityStarted(true)        SetActivityStarted(false)   
  m_activityStated = true
                                  m_activityStarted = false
                                  WriteToDB()               false
  WriteToDB()                                               false
因此,db显示了m_…=最近设置的状态x线。这没关系

这是一种合理的使用方法还是有更好的方法


<> >编辑[写到“我只关心最后一个状态-命令不重要”< /P> > P>我不是C++的家伙,但是我认为如果你没有同步的话,写它是安全的。

我不是C++的家伙,但是我认为如果你没有同步的话,写它是安全的。

<不,它不安全。< /P> 编写m_activityStarted和其他代码所生成的代码可能是原子代码,但不是Garantued。另外,在setters中,您可以做两件事:设置布尔值并进行调用。这绝对不是原子的

你最好用某种锁在这里同步

例如,一个线程可能会调用第一个函数,在该线程进入“WriteDB()”之前,另一个线程可能会调用另一个函数并进入WriteDB(),而没有第一个线程进入。然后,可能状态以错误的顺序写入数据库

如果您担心死锁,那么您应该修改整个并发策略。

不,这不安全

编写m_activityStarted和其他代码所生成的代码可能是原子代码,但不是Garantued。另外,在setters中,您可以做两件事:设置布尔值并进行调用。这绝对不是原子的

你最好用某种锁在这里同步

例如,一个线程可能会调用第一个函数,在该线程进入“WriteDB()”之前,另一个线程可能会调用另一个函数并进入WriteDB(),而没有第一个线程进入。然后,可能状态以错误的顺序写入数据库


如果你担心死锁,那么你应该修改你的整个并发策略。

你可以用bools解决它,但是如果正在更改的静态对象类型非常复杂,那么可怕的事情就会发生。我的建议-如果您要从多个线程进行写入,请始终使用同步对象,否则您迟早会被咬。

您可以使用bools进行操作,但如果正在更改的静态对象类型非常复杂,则会发生可怕的事情。我的建议-如果您要从多个线程写入,请始终使用同步对象,否则您迟早会被咬。

这不是一个好主意。有许多变量会影响不同线程的计时

如果没有某种类型的锁,您将无法保证具有正确的最后状态

有可能两个状态更新被无序写入数据库


只要锁代码设计正确,死锁就不应该是这样一个简单过程的问题。

这不是一个好主意。有许多变量会影响不同线程的计时

如果没有某种类型的锁,您将无法保证具有正确的最后状态

有可能两个状态更新被无序写入数据库


只要锁定代码设计正确,死锁就不应该是这样一个简单过程的问题。

这里看起来有两个问题

#1是您的布尔赋值不一定是原子的,即使它是代码中的一个调用。所以,在引擎盖下,你可能有不一致的状态。如果线程/并发库支持,您可以研究使用原子_set()


#2是阅读和写作之间的同步。从代码示例来看,WriteToDB()函数似乎写出了所有4个变量的状态。WriteToDB在哪里序列化?您是否会遇到这样的情况:thread1启动WriteToDB(),读取m_activityStarted但未将其写入数据库,然后被thread2抢占,而thread2一直写入m_activityStarted。然后,thread1继续,并完成将其不一致状态写入数据库。至少,我认为在进行数据库更新所需的读访问时,您应该对锁定的静态变量具有写访问权限。

这里似乎有两个问题

#1是您的布尔赋值不一定是原子的,即使它是代码中的一个调用。所以,在引擎盖下,你可能有不一致的状态。如果线程/并发库支持,您可以研究使用原子_set()

#2是阅读和写作之间的同步。从代码示例来看,WriteToDB()函数似乎写出了所有4个变量的状态。WriteToDB在哪里序列化?您是否会遇到这样的情况:thread1启动WriteToDB(),读取m_activityStarted但未将其写入数据库,然后被thread2抢占,而thread2一直写入m_activityStarted。然后,thread1继续,并完成写入
#define RUN_UNDER_MUTEX_LOCK( MUTEX, STATEMENTS ) \
   do { (MUTEX).lock();  STATEMENTS;  (MUTEX).unlock(); } while ( false )

class StatusCache
{
public:
    static void SetActivityStarted(bool activityStarted)
        { RUN_UNDER_MUTEX_LOCK( mMutex, mActivityStarted = activityStarted );
          WriteToDB(); }
    static void SetActivityComplete(bool activityComplete);
        { RUN_UNDER_MUTEX_LOCK( mMutex, mActivityComplete = activityComplete );
          WriteToDB(); }
    static void SetProcessReady(bool processReady);
        { RUN_UNDER_MUTEX_LOCK( mMutex, mProcessReady = processReady );
          WriteToDB(); }
    static void SetProcessPending(bool processPending);
        { RUN_UNDER_MUTEX_LOCK( mMutex, mProcessPending = processPending );
          WriteToDB(); }

private:
    static void WriteToDB(); // read data under mMutex.lock()!

    static Mutex mMutex;
    static bool  mActivityStarted;
    static bool  mActivityComplete;
    static bool  mProcessReady;
    static bool  mProcessPending;
};