0

ワーカー スレッドは、データベースの更新を処理します。アプリケーションが終了したら、アプリケーションを終了したいのですが、データベースの一貫性を失わないようにします。したがって、重要なデータベース操作の前にフラグを使用します。しばらくすると、コードは if でいっぱいになります。

      void MyWorkerThread::RunMethod(){
      if (false == m_Manager->GetShutdownFlag()) {
         DoSomethingOnDB();
      }
      if (false == m_Manager->GetShutdownFlag()) {
         DoSomethingMoreOnDB();
      }
      ...

それで、多くのifをスパムせずにシャットダウンを処理する他の方法はありますか?

4

5 に答える 5

2

メインスレッドがワーカースレッドを待機できるように、同期オブジェクト(イベント、ロック、ミューテックス、セマフォ、クリティカルセクションなど)などを介してスレッドを同期することをお勧めします。

ここに競合状態があります: 条件が評価された直後で、ifDB 操作が実行される前に、シャットダウン フラグが発生した場合はどうなるでしょうか?

これは、よく知られた同期プリミティブとしてミューテックスを使用した図ですが、もっと良い方法があります。

メインスレッド:

int main() {
    ... wait for signal to exit the app
    // the DB operations are running on another thread
    ...
    // assume that we start shutdown here
    // also assume that there is some global mutex g_mutex
    // following line blocks if mutex is locked in worker thread:
    std::lock_guard<std::mutex> lock(g_mutex); 
    Cleanup(); //  should also ensure that worker is stopped
}

ワーカー スレッド:

void MyWorkerThread::RunMethod() 
{
  {
    std::lock_guard<std::mutex> lock(g_mutex); 
    DoSomethingOnDB();
  }
  // some other, non locked execution which doesn't prevent
  // main thread from exiting
  ...
  {
     std::lock_guard<std::mutex> lock(g_mutex);
     DoSomethingMoreOnDB();
  }
}

すべてのロックを繰り返したくないのは明らかなので、ラップする必要があります。

  void MyWorkerThread::RunMethod() 
  {
    Execute(DoSomethingOnDB);
    ...
    Execute(DoSomethingMoreOnDB);
  }

  void MyWorkerThread::Execute(DatabaseFn fn) 
  {
     std::lock_guard<std::mutex> lock(g_mutex); 
     fn();
  }
于 2013-04-11T11:54:04.763 に答える
1

アプリケーションに既に ReaderWriter ロックがありますか? データベースのクローズを書き込み操作として扱い、開始する前にライター ロックを取得する必要があります。その後、クローズが進行中になると、他の Read (Reader Lock を取得する) または Write 操作 (Writer Lock を取得する) を開始できなくなります。

于 2013-04-11T11:58:47.837 に答える
1

コードにはパターンがあります。つまり、関数として抽象化できます。

void MyWorkerThread::execDBCommand(auto cmd){
    if  (! m_Manager->GetShutdownFlag()) {
        cmd();
    } else throw std::runtime_error("shutdown"); // or a custom exception
}

try...catchその例外の外側を使用してRunMethod、より直接的に処理を中断します。

ただし、シャットダウン フラグはスレッドのシグナルとして処理する方が適切かもしれません。スレッドは保留中のトランザクションをロールバックし、処理を中止します。各命令の前に状態をチェックする必要はありません。また、DB 呼び出し中にシグナルをマスクする必要があります。

もちろん、プログラムのアーキテクチャに依存します。

于 2013-04-11T12:14:28.727 に答える
0

Do 関数が何かを返す場合は、&& または || を実行できます。それらのいずれかが終了条件である「false」または「true」を返すとすぐに、処理を停止します。

操作中に (または実行する直前に) シャットダウン フラグが別のスレッドによって設定された場合はどうなりますか? また、このプロセスを実行した場合はどうなりますか?

于 2013-04-11T11:55:25.367 に答える
0

フラグの使用は、データベースを使用するさまざまなメソッドに限定されます: DoSomethingOnDB、DoSomethingMoreOnDB ...

ミューテックスとロックを適切に使用すると仮定すると (これはここには表示されません)、データベース関連のメソッドを複合メソッドに集めて、そこでデータベースをロックし、その単一のメソッドで単一のチェック ブール操作を実行して、単一のスレッドだけがデータベースを作成できるようにします。一度に操作。

于 2013-04-11T12:09:17.220 に答える