🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

排他制御

排他制御とは、特定のファイル・データへのアクセスや更新を制御することです。特にファイルやデータベースへ書き込みを行う際、データの整合性を保つため別のプログラムによる書き込みを一時的に制御することを指します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

2335閲覧

C++言語 シンプルな排他制御の問題

Timosy

総合スコア3

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

排他制御

排他制御とは、特定のファイル・データへのアクセスや更新を制御することです。特にファイルやデータベースへ書き込みを行う際、データの整合性を保つため別のプログラムによる書き込みを一時的に制御することを指します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/01/15 11:53

編集2021/01/15 13:10

#質問 
以下の排他制御を使う問題が上手くいきません.
正しい書き方,mutexの使い方を教えてほしいです.

Question

1共有メモリ内で,2つのint型の変数A,Bを用意して,その初期値をA=100, B=0とする. 2そして2つのプロセスでそれぞれ変数A,Bに対して以下の処理を行うようにせよ. 3 4プロセス1 : 変数Aから変数Bへ1ずつ値を移動させて,これをA=0,B=100になるまで繰り返す.(transfer.c) 5プロセス2 : プロセス1の途中経過を出力(AとBの合計値が常に100であることを出力)する(observe.c) 6 7このとき排他制御を用いない場合にA+Bが常に100になるとは限らないことと,排他制御を用いる場合にA+Bが常に100になることを示せ.

#考えたこと
以下が自分で書いたコードです.

C++

1//インクルードライブラリ 2#include <iostream> 3#include <windows.h> 4#include <mmsystem.h> 5#include <thread> 6#include <mutex> 7 8//関数のプリ宣言 9void ThreadProcessP1(); 10void ThreadProcessP2(); 11 12//Mutex宣言 13std::mutex mutex; 14 15int A = 100; 16int B = 0; 17int C = 0; 18boolean i = false; 19 20int main() 21{ 22 //マルチスレッドスタート 23 std::thread thP1(ThreadProcessP1); 24 std::thread thP2(ThreadProcessP2); 25 26 //マルチスレッド終了 27 thP1.join(); 28 thP2.join(); 29} 30 31//スレッドP1 32void ThreadProcessP1() 33{ 34 while (A > 0) 35 { 36 { 37 std::lock_guard<std::mutex> lock(mutex); 38 A -= 1; 39 Sleep(1);// このスリープを重い処理と見立てる 40 B += 1; 41 } 42 } 43 44} 45 46//スレッドP2 47void ThreadProcessP2() 48{ 49 while (B < 100) 50 { 51 std::lock_guard<std::mutex> lock(mutex); 52 printf("A=%d, B=%d, A+B=%d\n", A, B, A+B); 53 } 54}

このとき排他制御を用いない場合に,A+Bの値が100にならないときがあることは確認できましたが,排他制御を行う時(上記コード)を実行すると上手くいきません。
排他制御にはセマフォが良いと聞きましたが使い方がいまいち理解できないのでどなたかご教授ください

#実行結果
このときAとBが1ずつずれていき,A+Bが常に100にならなければならないのですが,最後の最後で一気に値が変わっている状況です.

Result

1A=100, B=0, A+B=100 2A=100, B=0, A+B=100 3A=100, B=0, A+B=100 4A=100, B=0, A+B=100 5A=100, B=0, A+B=100 6A=100, B=0, A+B=100 7A=100, B=0, A+B=100 8A=100, B=0, A+B=100 9A=100, B=0, A+B=100 10A=100, B=0, A+B=100 11A=100, B=0, A+B=100 12A=100, B=0, A+B=100 13A=100, B=0, A+B=100 14A=100, B=0, A+B=100 15A=100, B=0, A+B=100 16A=100, B=0, A+B=100 17A=100, B=0, A+B=100 18A=100, B=0, A+B=100 19A=100, B=0, A+B=100 20A=100, B=0, A+B=100 21A=100, B=0, A+B=100 22A=100, B=0, A+B=100 23A=100, B=0, A+B=100 24A=100, B=0, A+B=100 25A=100, B=0, A+B=100 26A=100, B=0, A+B=100 27A=100, B=0, A+B=100 28A=100, B=0, A+B=100 29A=100, B=0, A+B=100 30A=100, B=0, A+B=100 31A=100, B=0, A+B=100 32A=100, B=0, A+B=100 33A=100, B=0, A+B=100 34A=100, B=0, A+B=100 35A=100, B=0, A+B=100 36A=100, B=0, A+B=100 37A=100, B=0, A+B=100 38A=100, B=0, A+B=100 39A=100, B=0, A+B=100 40A=100, B=0, A+B=100 41A=100, B=0, A+B=100 42A=100, B=0, A+B=100 43A=100, B=0, A+B=100 44A=100, B=0, A+B=100 45A=100, B=0, A+B=100 46A=100, B=0, A+B=100 47A=100, B=0, A+B=100 48A=100, B=0, A+B=100 49A=100, B=0, A+B=100 50A=100, B=0, A+B=100 51A=100, B=0, A+B=100 52A=100, B=0, A+B=100 53A=100, B=0, A+B=100 54A=100, B=0, A+B=100 55A=100, B=0, A+B=100 56A=0, B=100, A+B=100

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2021/01/15 13:21 編集

[質問内容が改修されたので指摘内容を削除]
Timosy

2021/01/15 13:22

コメントありがとうございます。 おそらくそれと同様の間違いに気づきコードを修正したのですが,反映されてないでしょうか?
dodox86

2021/01/15 13:24

コメントを投稿した後にコードの修正を確認しました。不要な指摘となったので削除しました。
guest

回答1

0

ベストアンサー

このときAとBが1ずつずれていき,A+Bが常に100にならなければならないのですが,最後の最後で一気に値が変わっている状況です.

恐らくですが、実行環境に依存してそのような結果になっています。動作させているPCが速過ぎて、ThreadProcessP2スレッドが走り始めてA=100, B=0の状態がしばらく続き、その状態を出力し続け、ThreadProcessP1の実行が割り当てられたら一気にA=0, B=100まで処理を実行した後、ThreadProcessP2に実行が移っています。ちなみに当方の非力で遅いWindows PC(Windows 10の Cygwin環境)で試したところ、「A + B = 100」で正しく動きましたし、std::lock_guard<std::mutex> lock(mutex);を除去すると「A + B ≠ 100」となりました。

ご提示のコードでは重い処理をシミュレートする為にWindows APIのSleepを使い、Sleep(1);のように1ミリ秒をセットしていますが、もっと大きい値、たとえば200ミリ秒とか500ミリ秒をセットしてみてください。尚、1ミリ秒をセットしても実際は数10ミリ秒程度の不定な値でしかスリープできていません。Windows自体の制限事項です。

投稿2021/01/15 14:04

編集2021/01/15 14:08
dodox86

総合スコア9256

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Timosy

2021/01/15 14:25

確かに異なる実行環境で行った場合大きく違う結果になることが確認できました. 理解しました.ありがとうございます.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問