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;
};