• ベストアンサー

C++でシングルスレッドで同期処理すべきか?

 こんばんは。 C++でプログラミングの勉強をしている者ですがシングル スレッドで同期処理をし、メイン処理からそのスレッドを実行した場合は スレッドの処理が終わるまで、そのスレッドに扱われる変数にアクセスできないという 認識で会っていますか? そもそも同期処理というのが、マルチスレッドで、同じメソッドを扱う場合、片方の処理が 終わるまでもう片方の処理は待機しているという認識で合ってますか? メイン処理からスレッドを作成し、スレッドの動きを止め、あるタイミングでスレッドの 処理を再開させる処理をメイン処理で実装することはできるでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • nda23
  • ベストアンサー率54% (777/1415)
回答No.2

>シングルスレッドで同期処理 スレッドの意味を理解していますか? スレッドが一つしかないのに、何と「同期」するんですか? >スレッドに扱われる変数にアクセスできない そんなことはありませんよ。 終了しなくても同期が必要なことはあるし、それに使う イベントやセマフォハンドルは双方で操作します。 その他、特定のフラグやログファイルハンドルなども 双方で使う可能性が高いです。 >同期処理というのが、マルチスレッドで、同じメソッドを扱う 何かの勘違いですかね? 「同じメソッド」ではなく、どこかの一点で、状態を合わせる というのが同期です。 例えば、ファイルのコピーを考えましょう。 入力と出力を別々のスレッドで処理する場合、出力側は 入力が完了するまで、実行できませんよね。 だから、入力側が完了したことを通知するまで、待機 します。入力側は入力が完了したら、出力側にそのことを 通知し、今度は出力が完了するまで待機します。 入力側はReadだし、出力側はWriteだから同じメソッドでは ありません。 今の例をプログラムしたらどうですか? バッファを二つ(便宜的にAとB)用意し、Aに入力したら 出力側に通知して、引き続きBに入力します。出力側は 通知があったらAを出力します。次に通知があったら、 今度はBを出力します。つまり、「Bへ入力」「Aから出力」が 同時に実行されることになります。 この時、双方のスレッドではバッファ、ファイル、入力バイト数、 同期用のイベントなど、同じ変数を参照/操作することになる はずです。 このような方法でコピーすると、理論上はシリアルに実行する 場合の半分の時間で転送が可能です。 同一デバイスのファイルの転送では効果が少ないのですが、 通信を利用して異なるPC間の転送などを行う場合は非常に 有効です。経験的に実行時間は1/2以下になります。 つまり、理論値よりも高速です。 尚、ついでに両方のスレッドで同じファイルにログを出力する ようにすると、何も制御しない時は出力が重なって内容が 崩れます。これを防ぐためミューテックスを使うことになる でしょう。これで、同期制御と排他制御の両方が学べます。

DEADSPACE566
質問者

お礼

ミューテックスは、二重起動防止に役立ちました。 それを学んでおいたほうがよさそうですね。 IO処理で同期処理をし、ミューテックスでログが被るのを 防ぐんですね。 勉強します。

DEADSPACE566
質問者

補足

同期制御と排他制御の勉強が足りていないと思いました。 そこらへんはしっかり学んでおくべきですね。

その他の回答 (2)

noname#208507
noname#208507
回答No.3

> メイン処理からそのスレッドを実行した場合 メイン処理ですでにスレッドが一つ。メイン処理から新しくスレッドを作って実行すると、合計でスレッド二つ。その時点でもうシングルスレッドではないです。 > そのスレッドに扱われる変数にアクセスできない その変数がスコープ内にあり、排他制御されていんければ、どのスレッドからもアクセスできるでしょう。 > 同じメソッドを扱う場合、片方の処理が終わるまでもう > 片方の処理は待機しているという認識で合ってますか? それはモニタのことですね。同期処理には違いありませんが、全ての同期がモニタではありません。セマフォやランデブなど同期には様々な形態があります。 > スレッドの動きを止め、あるタイミングでスレッドの > 処理を再開させる処理をメイン処理で実装することは 察するにランデブ(複数のスレッド同士の待ち合わせ)を実現したいのではないでしょうか。 既存の実装(例えば C++CSP2 [http://www.cs.kent.ac.uk/projects/ofa/c++csp/] のチャネル)を使うか、あるいは専門の文献で調べれば同等の処理をセマフォやモニタを駆使して自力で実装することもできます。

DEADSPACE566
質問者

お礼

ランデブなんて言葉は初めて聞きました。 そんなスレッド処理があるんですね。 そういったものを調べて対処しようと思います。

  • wormhole
  • ベストアンサー率28% (1622/5658)
回答No.1

同期処理と排他制御を混同されていませんか?

DEADSPACE566
質問者

お礼

なるほど確かにそうですね。 自分が説明しているものは排他制御ですね。 同期処理ではありませんでした。 非同期処理とは違うんですね。

DEADSPACE566
質問者

補足

後で調べてみます。

関連するQ&A

  • 非同期プログラミングは必ずマルチスレッド?

    非同期プログラミングは必ずマルチスレッドプログラミングになりますか? ここでいう非同期プログラミングとは、 何かのメソッドを実行してその処理(処理Aとする)の結果を待たずに次の処理Bを実行できて、処理Aが終わったらコールバックやデリゲートで、あらかじめ決められたメソッド(finishとする)が呼ばれるといったものです。 処理Aを実行するメソッドを呼ぶ ↓ すぐに処理Bを実行開始(このときバックグラウンドで処理Aが走っている) ↓ 処理Aが終了したのでfinishメソッドが実行される 例えば、Objective-CのNSURLConnectionで非同期通信するときのようなやつです。 こういった非同期プログラミングは、必ずマルチスレッドを使うことになりますか? 普通、別スレッドで処理させるときはスレッド用のライブラリを使うなどして明示的にマルチスレッドプログラミングをしますが、上のように非同期のメソッドを使うと、その裏で自動的に別のスレッドが動くのでしょうか。 それとも、単一スレッドのみで、非同期プログラミングできるでしょうか。 なお、特殊な言語やOSによっては、いくらでも可能性があると思いますので、 メジャーな環境(Windowsや、スマホ) のみに限定してお願いします。言語で言うと、C、C++、Objective-C、Javaあたり。 また、上の「処理A」が終わったとき、メソッド「finish」が呼ばれるとすると、 処理Bの実行中にどのようなタイミングでfinishが呼ばれるのでしょうか。 処理Bはどのような形でfinishに切り替わるのでしょうか。いきなりfinishに処理を奪い取られるのでしょうか

  • ManualResetEvent非同期処理で固まらないようにする

    HttpWebRequestの非同期処理からデータを取得する際に ManualResetEventで完了したかどうかを待機していますが、 待機中はフォームが固まってしまいます。 非同期処理のIAsyncResult中にApplication.DoEvents();をしたら、 例外処理として落ちてしまいます。 ManualResetEvent非同期処理で固まらないようにするには、 マルチスレッドでイベントを起こすしかないのでしょうか? それともほかにいい方法があるのでしょうか?

  • メソッドの処理の同期化

    いつもお世話になっています。 メソッド処理の同期化についてなのですが、 いろいろ調べてみたのですが、いまいちうまく実行できません。 ソースを考えてみたのですが、どこがどう悪いのかご指摘お願いできますでしょうか? 以下のクラスがある場合で public void Add(){ synchronized(this){ System.out.println("待機しています!"); //おそらくここら辺にwait()/notify()処理が来るきがする //同期中に行わない処理をここに記載する? } System.out.println("Addメソッド実行しました"): } public void Change(){ synchronized(this) { //おそらくここら辺にwait()/notify()処理が来るきがする //同期中に行わない処理をここに記載する? //一時停止 処理時間をずらすためループを使用 try { for(int a=0;a<3;a++){ System.out.println("a="+a); Thread.sleep(10000); } }catch (InterruptedException e) { } System.out.println("Changeメソッド完了です"); } } このとき、Add対Change/Add対Addといった形で同期化処理をしたいのですが、どうしてもうまくできません。 仮にThreadを使用して実行してみようとしたのですが、 順番に実行されてしまいます。 したいのが、 1.Addメソッド実行 2・Addメソッド実行 この場合、現状だと a=0 a=0 a=1 a=1 a=2 a=2  と表示されてしまうので、 a=0 a=1 a=2 a=0 a=1 a=2  と表示することはできるのでしょうか? 原因として、wait()/notify()が記載されていないことが影響していると思うのですが。 宜しくお願いします。

  • 割り込み処理のシミュレート

    現在開発している組み込み系システムのシミュレートをVCで行いたいと考えています。 組み込み系のシステムは簡単に言うと、 普段はメインループでくるくる回っており、1ms毎にタイマ割り込みが発生し、変数の値を書き換え、メインループではその変数の変化によって何か処理を実行するというものです。 このようなシステムをVCでできるだけ同じようにシミュレートするため、マルチスレッドを用いようと考えているのですが、以下の性質を実現することは可能でしょうか? ・メインスレッド実行中はタイマ割り込みスレッドは割り込み可能。 ・タイマ割り込みスレッド実行中はメインスレッドは割り込んでこない。 ・メインスレッドで特定の区間タイマ割り込みスレッドの割り込みを禁止できる。 ・高速シミュレートを行いたいため、割り込みの禁止などはできるだけ低負荷で行いたい。(ミリ秒単位だとNG) ・複数の割り込みスレッドがある場合、各スレッドごとに割り込みレベルを設け、このレベル以下を割り込み禁止など行いたい。 スレッド以外の実現方法などあればそちらもご教授願いたいです。 よろしくお願いします。

  • タイマー関数とマルチスレッドについて

    こんばんわ。 マルチスレッドプログラミングを行なっています。 コンパイラはVC++.NETでC言語を利用しwin32 apiを用いています。 スレッドを_beginthreadex関数でスレッドを2つ生成し、WaitForSingleObject,SetEvent,ResetEvent関数によるイベント同期を利用し、2スレッドの同期をはかっています。 [質問内容] 以下のように、スレッド2でWaitForSingleObject関数にてスレッド2を待機状態にし、スレッド1のSetEvent関数にて待機しているスレッド2を再開させる方法をとっています。 例えば、タイマーをスタート後に待機状態になり、スレッド2が再開後タイマーストップするとした場合、スレッド2が待機状態のときもタイマーを動き続けているのでしょうか? ・スレッド1 SetEvent(hEvent[0]); ・スレッド2 SUSPEND_INTERVAL=20 if(Num%THREAD_SUSPEND_INTERVAL==0){ timestart=timeGetTime();←タイマースタート WaitForSingleObject(hEvent[0],INFINITE); ResetEvent(hEvent[0]); timestop=timeGetTime();←タイマーストップ } よろしくお願いします。

  • C++マルチスレッド処理について

    こんにちは 現在スレッドを作成して,マルチスレッド処理をしようとしているのですが, 全然理解できないので皆様のお力をお貸し下さい。 やりたい事は, (1) メインスレッドからスレッド1を作成。 (2) スレッド1では,ひたすらファイルなどからデータを取得させる。(読み込めなくなるまで) (3) メインスレッドでは,時々スレッド1を止めて,再度処理を続行させたい。 class Sample { public: // Sampleオブジェクト作成,同時にスレッド1を作成 Sample* create(); // スレッド1を止めて,再度動かす void process(); private: // この関数をスレッド1で処理させる // 内部では,読み込めなくなるまで無限ループ? void get(); }; スレッドに関してはイメージが湧くのですが, mutex (必要ですか?) に関しては一向に理解できません。 何を排他制御するのでしょうか。オブジェクト? 関数? 複雑ではなさそうなのですが,今までシングルスレッドの処理のみ書いていたため ピンときません。 よろしくお願い致します。

  • Delphiのマルチスレッドの割り込み処理について

    Delphiのマルチスレッドの割り込み処理について教えて欲しいのですが、ファイルをスレッドオブジェクトで作成して クラス名.Execute関数内でSynchronizeメソッドを使用しています。 本にはSynchronizeメソッドは「渡したメソッドが実行され終了するまで待ちます」と書いてあり、テストプログラムを作成してもそうでした。ということはSynchronizeメソッドは普通の関数と一緒のような気がしてしまうのですが、違うのでしょうか? Procedure MyThread.Execute begin Synchronize(AAA); AAAの処理が終了するまで待機している end; Procedure TmyThread.AAA; begin 'したい処理' end;

  • JavaScriptの非同期処理について。

    頭の悪い質問かもしれません。 ””非同期処理とは、あるタスクを一時的にスレッドから切り離すことで、後続の処理の進行を止めることなく別のタスクを実行できる処理方式のことである。””https://qiita.com/komaitaira/items/54b5c9f3d54695974704 と書いてあるのですが。 スレッドから切り離されたタスクっていうのは、例えばどこで何をしてるのですか? 例えば、ファイルの読み書きを非同期処理で実行した場合。 ファイルの読み込みはスレッドから切り離されるということだと思うのですが、スレッドから切り離されたら、「ファイルの読み込み」という動作はどこで行われているのですか? よろしくお願いします。

  • マルチスレッドプログラミングの利点について

    はじめまして。 質問があります。 現在マルチスレッドプログラミングについて学習しているのですが、 学習を進めていくうちにある疑問が思いつきました。それは、 マルチスレッドで実装した方がよい場合とシングルスレッドで実装 した方がよい場合の区別がよくわからないということです。マルチスレ ッドで実装する利点は、例えば、応答性を向上させるとか、 入出力操作が関わっているときにCPUの空き時間を利用して別スレッド で処理を行わせることによってスループットを向上させることぐらいしか思いつきません。また、CPUが1個しかない環境では、 CPUをフル活動するようなプログラムでは、下手にマルチスレッドで 実装するよりもシングルスレッドで実装したほうが排他制御しない 分だけ処理スピードは上であると思っているのですが、間違いでしょうか?マルチスレッドで実装した場合の利点は上述したこと以外にも 何かあるのでしょうか?ご教授お願いします。

    • ベストアンサー
    • Java
  • Threadのinterruptメソッドについて

    javaの勉強をしているんですが、Threadのinterruptメソッドの説明が「そのスレッドがwaitで待機している場合は、それを再開してwaitにInterrupException をスローさせる」と説明が書いてあるのですが、意味が理解できません。 スローさせるスレッドは待機状態であったスレッドを指し例外がスローされて、catch文に処理が移るのでしょうか? 初心者なので分かりやすく説明をお願い致します。

専門家に質問してみよう