• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:クリティカルセクションの使用箇所について)

クリティカルセクションの使用箇所について

このQ&Aのポイント
  • クリティカルセクションを使用してスレッドセーフな処理を実現する方法について説明します。
  • スレッドAで書き換えが行われる変数とスレッドBからの読み取り専用アクセスがある場合、それらを一つのクリティカルセクションで保護することでスレッドセーフな処理が可能です。
  • スレッドAからしか書き換えが行われない場合でも、その変数と他のスレッドからの参照がある場合には、それらを囲むクリティカルセクションで保護することが重要です。

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

  • ベストアンサー
  • Dodonpa2
  • ベストアンサー率82% (19/23)
回答No.1

そのデータ群に関してはそれでスレッドセーフになると思います。わかりやすくしたければ、共有するデータ群を別クラスにして、そのクラスに同期オブジェクトを埋め込んでやれば記述はすっきりするかもしれません。

LongSecret
質問者

お礼

どうもどうも、ありがとうございます♪ これが確認できればすっきりです。今後も役に立つことは間違いありません。 >共有するデータ群を別クラスにして、そのクラスに同期オブジェクトを埋め込んでやれば記述はすっきりするかもしれません。 なるほど…! 確かに、コスト(最小限の呼び出し)と利便性(関数名などで分かりやすく、かつ見た目上短く表記できる)の両方をとろうとするなら そのためだけにクラスを作ってしまうという手も、状況次第で十分考えられそうですね。 私が質問時に関係性の深い変数といったのは、具体的にはポインタのポインタ(動的確保をする)とその確保時の要素数を示す整数のことでしたが クラスのコンストラクタとデストラクタを利用して、関数の出口が複数ある場合にクリティカルセクションの解除忘れを防ぐ。という別クラスの利用アイデアは、読んだことがあったのですが それについては、今回は頻繁に呼び出される可能性も否定できなかったので、コンストラクタとデストラクタのオーバーヘッドを考えて使っていませんでした。 依然、マルチスレッド用描画(GDI)関連に関しては専用クラスを作ったことがあったのですが、今回保護する変数が2つのみだったので、そこで「別クラスを作る」という方向に対しては思考停止していました。 しかし、そのためのクラスといっても、そういう組み方と限る必要はなく、Dodonpa2さんがおっしゃるように、このことのために独自に作るとすれば、コンストラクタやデストラクタを呼ぶ必要ないように書き、インライン展開で関数呼び出しのオーバーヘッドの可能性を完全に撤廃などできれば コスト面で劣らない書き方も可能(ただし、その場合は分かりやすくするという意味あいのみになるかもしれませんが) あるいは、今回の場合にも流用できる可能性として 「何かを動的配列確保するためのポインタ」と「要素数を示す整数」と「クリティカルセクション」をもつようなtemplateのクラスを、インライン展開をしっかり意識して作っておけば、同じようなことには十分使いまわせるかもしれません。 その辺、どういう手を使うかは、やはりプログラミングの醍醐味ですね。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • クリティカルセクションの用途について

    クリティカルセクションの用途について 現在VC++2008でEnterCriticalSectionを使用して複数の変数を管理していますが、 アプリケーションの初期化のとき(シングルスレッドのとき)に一度だけ書き込み、その後複数のスレッドから読み込む変数の場合、読み込み時にクリティカルセクションにする必要があるでしょうか?

  • マルチスレッドと変数

    マルチスレッドのプログラムを組んでいます。 そこで、複数のスレッドからアクセスする変数があるのですが、これの扱いについて解らないことがあります。 ・変数を複数のスレッドから書き換える場合は、予想していた結果と違うことになる。 ここまではいいのですが、 ・変数を複数のスレッドから、参照だけするのは問題ない。 ・変数を複数のスレッドから、参照し、書き換えるのはひとつのスレッドだけならば、問題はない。 (上の"変数"は全て、Lockをかけていない状態です。) という認識をもっているのですが、これは間違いなのでしょうか? 「参照だけならばLockはかけなくてよい」というのをどこかで読んだような覚えがあり、そのまま勝手に最後の推測をしています。 現状ではうまくいっているようなのですが、とても不安です。 もしくは、状況、環境、コーディングによって上の仮定は成立したり、成立しなかったりするのでしょうか?環境はC#ですが、もしどのような言語、環境であっても一般的に、同じような結果になるのなら、それも合わせてご教授お願いします。

  • マルチスレッドについて。

    今、大きな配列を元に処理を行うプログラムを作成しています。 シングルスレッドでも十分速度を向上するようチューニングに成功しましたが、マルチスレッド化をすればさらに速度を向上させることができるだろうと考え、先日マルチスレッドかに成功しました。 しかし・・・奇妙な現象が起こりました。 マルチスレッドで性能を引き出すには、排他制御はないほうが良いと考え、メモリは食いますがスレッドに与える入力情報(大きな配列)を2つ用意し、排他制御なしの2スレッドを実行できるようにしました。しかしやはりメモリを消費しすぎてしまうため、配列にアクセスする部分のみ排他制御を行うようクリティカルセクションを設定し入力情報を2スレッドで共有して処理を行うよう組み替えました。 結果、やはり排他制御なしの場合よりはるかにスピードダウンしてしまい、シングルスレッドより少し早い処理時間で終了してしまいました。 余りにも悔しいため、ちょっと危険な実験だとは思いましたが、入力情報を2つのスレッドで共有しているにもかかわらず、排他制御の部分、つまりクリティカルセクションを取り除いて実行してみようと考えました。予想としては同時にアクセスし衝突が起きてエラーで停止してしまうと考えましたが・・・・・・ 結果なぜかエラーなく処理をし続け、普通に終了してしまいました。 これはなぜでしょう? 偶然にも共有情報に同時にアクセスすることがなかったためでしょうか?

  • JSPのスレッドセーフについて

    Strutsを用いて開発しております。 「スレッドセーフにするように」と言われ、 JSPのコードを見ると<% %>で囲まれた部分がありました。 こちらで他の質問を見させていただいたときは 「<%! %>で囲まれた部分はインスタンス変数として扱われる」 とあったのですが、<% %>で囲まれた部分に定義された変数は ローカル変数なのでスレッドセーフであると考えて 間違いないでしょうか? (JSPから生成されたjavaコードを見ると、_jspServiceメソッドの中で  定義されていました。)

    • ベストアンサー
    • Java
  • パブリック変数を宣言する時に・・・

    エクセルVBAの質問です。 モジュールAとBがあるとしまして、 Aの中にあるプロシージャからBの中のプロシージャを呼び出す場合、 変数を引き渡したいとしたらパブリック変数を使いますよね? この場合宣言は、 Aの宣言セクションでするのか、 Bの宣言セクションでするのか、 あるいは両方で同じ変数を宣言するのか、 どれなんでしょ?

  • クリティカルセクションという言葉は、(区間名でなく)同期オブジェクト名として一般的?

    Winのマルチスレッドプログラムで、各スレッドから「不可分性を要する区間(=クリティカルセクション)への進入権を得る」為、下の同期オブジェクトを使うと思います。 1.クリティカルセクション 2.ミューテックス 3.セマフォ この時、1.は標準語と思って良いでしょうか?それともWinの方言でしょうか? ある他環境(マルチプロセス&マルチスレッド)の説明文書では、"クリティカルセクション"という言葉の代わりに"軽量ミューテックス"と呼ばれていました。 又、↓では、クリティカルセクションが"区間名"としてのみ説明されており、同期オブジェクト名に関する事は書かれていません。 http://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AA%E3%83%86%E3%82%A3%E3%82%AB%E3%83%AB%E3%82%BB%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3 従って、クリティカルセクションは本来、区間名として使われるべきで、Winではたまたま同期オブジェクト名にも適用されたのかな?と思った次第です。 細かい事ですが、しっかり確認したいと思いました。どうぞ宜しくお願いします。

  • Javaのスレッドについて教えて下さい!

    AとBはpublic参照で、AはThreadを参照していて、BはObjectを参照しているとする。スレッドAはB.wait()を実行中の際に別のスレッドからAがwaitの実行を停止することを保証するために、一番信頼性のあるコードは、foo.notify(); とfoo.notifyAll()のどちらになりますか?また、他に良いコードはありますか?

    • ベストアンサー
    • Java
  • __threadを使うコードで、分割コンパイル→リンクを行うには?

    下記コードをビルド中、下記リンカエラーが出てしまい その解決方法を伺いたく質問させて頂きました。 ■コード [ t.hpp ] struct C { static int m; static void f(); }; [ a.cpp ] #include "t.hpp" __thread int C::m; [ b.cpp ] #include "t.hpp" void C::f(){ m = 0; } void main(){} ■リンカエラー C::m: TLS definition in a.obj section .tbss mismatches non-TLS reference in Debug/b.obj (静的メンバ変数C::mは a.cppでTLSとして定義されたけど、C::mを参照しているb.cppでは、非TLS扱いだから合わないよ!) ■試した事 ・t.hppのstatic int m; に、__threadを付加 → 付けないのと同じ扱いだった ・a.cppのコードをb.cppに統合したらOK → __thread変数の定義部と参照部を同じファイルにすると良さそう。が、会社の政治的な理由で不可... ■環境 ある組み込み環境でのGCC4.0.2 一日中試しましたが惨敗でした。ファイル構成を変えずにTLSの静的メンバ変数が使える方法をお教え頂けないでしょうか。どうか宜しくお願い致します。

  • Java Stringに関して

       お世話になります。  SJC-Pの学習をしているのですが、Stringに関して、とある教科書に  以下のように記述されていましたが意味がわかりません。  わかりやすく教えていただけたらと思います。  教科書の文章(以下)   同じリテラル文字列に再び出会った場合、コンパイラは既にプール内  に格納されている文字列を使います。(3つ以上の参照変数が同じ  文字列を参照する可能性があるため、この処理はスレッドセーフ  ではない。)  上記文章の( ) で囲まれた部分の意味がまったくわかりません。  よろしくお願いします。

  • スレッド処理内の変数の参照について

    大変困ってます。 今、親プロセスからスレッド内の変数に設定したいのですが方法がわかりません。 スレッドからの場合、普通行えばいいのでわかるのですが ・・・。 (詳細) メインプロセス(A) クリエートスレッド後のスレッド(B)  1.(A)で(B)をCreateThread  2.(A)の本処理で(B)の構造体にmemcpyの方法が    わかりません。  3.知っている方がいましたら教えていただけませんか。  4.読みずらい文章ですみません。宜しくお願いします。

このQ&Aのポイント
  • マゼンダとイエローのインクが綺麗に印刷されず、シアンとブラックが濃くプリントされます。ノズルクリーニングをやりすぎて、それだけでインクを消耗してしまっているのではないかと思うくらいです。
  • お使いの環境はWindows10で無線LAN接続です。
  • ブラザー製品についての質問です。
回答を見る