質問するログイン新規登録

Q&A

解決済

3回答

1365閲覧

デバッガで止めて発生するレースコンディションは実際に起こりえるかどうか

a.com

総合スコア922

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2024/09/23 04:35

0

0

タイトルの通りなのですが、デバッガで意図的にスレッドを止めてレースコンディションが起こせるとしたら
実際に起こりえると言えるのでしょうか?

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

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

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

maisumakun

2024/09/23 04:51

質問の前提としてうかがいたいのですが、「レースコンディションが起きる」と仮定してプログラミングを進めることに、何かしらの不都合がある状況なのでしょうか。
a.com

2024/09/23 04:53

コメントありがとうございます。レースコンディションは絶対に起こしてはいけないという前提です
JavaCommons

2024/09/23 05:42

スレッド間の競合は「排他処理」を適切に行うことで解決できます。 「排他処理」を最小化することで競合解決のためのパフォーマンスロスを最小化できます。 レースコンディション時のデータ破壊を防げばいいだけです。
guest

回答3

0

ベストアンサー

こんにちは。

質問部分に端的に回答すると、
デバッガで意図的に止めるなどの手段でレースコンディションを起こすことが可能なコードは、本質的に「レースコンディションが起きうるコード」ということになります。
レースコンディションを起こしてはいけない前提なら、そのコードは完全アウトです。

レースコンディションが起きないコードであれば、デバッガで止めるだけではレースコンディションは決して起こりません。
もちろんデバッガで止めた上で、内部状態を手で書き換えたりしたらレースコンディションを起こせるかもしれませんが、それは実際の動作中には起こりえないので、また別の話です。

投稿2024/09/24 08:28

tamoto

総合スコア4433

a.com

2024/09/25 01:47

ありがとうございます!すっきりしました
guest

0

デバッガで止めなくても・・・
スレッド間の共有資源(共有データ)に対する競合は、Theread.sleep(ms) などをスレッドのコードに入れたりすることでも起こせますね。
スレッドは独立したCPUで別々に実行しているようなものなので、共有資源(共有データ)をアクセスする場合には排他処理を必ず入れた方がいいと言えます

以下のソースコードを実行すると、50に近い値が表示されそうですが、そうなりません。

java

1class MyThread extends Thread { 2 private int count; 3 public MyThread(int count) { 4 this.count = count; 5 } 6 @Override 7 public void run() { 8 for (int i=0; i<this.count; i++) { 9 int total = ThreadDemo.total; 10 try { 11 Thread.sleep(1); 12 } catch (InterruptedException e) { 13 ; 14 } 15 total += 1; 16 ThreadDemo.total = total; 17 } 18 } 19} 20public class ThreadDemo { 21 public static int total = 0; 22 public static void main(String[] args) throws Exception { 23 MyThread t1 = new MyThread(25); 24 MyThread t2 = new MyThread(25); 25 t1.start(); 26 t2.start(); 27 t1.join(); 28 t2.join(); 29 System.out.println(ThreadDemo.total); 30 } 31}

次のコードのように、排他処理を入れることで、総和が必ず50になります。

java

1import java.util.concurrent.locks.Lock; 2import java.util.concurrent.locks.ReentrantLock; 3 4class MyThread extends Thread { 5 private int count; 6 7 public MyThread(int count) { 8 this.count = count; 9 } 10 11 @Override 12 public void run() { 13 for (int i = 0; i < this.count; i++) { 14 ThreadDemo.lock.lock(); 15 try { 16 int total = ThreadDemo.total; 17 try { 18 Thread.sleep(1); 19 } catch (InterruptedException e) { 20 ; 21 } 22 total += 1; 23 ThreadDemo.total = total; 24 } finally { 25 ThreadDemo.lock.unlock(); 26 } 27 } 28 } 29} 30 31public class ThreadDemo { 32 public final static Lock lock = new ReentrantLock(true); 33 public static int total = 0; 34 35 public static void main(String[] args) throws Exception { 36 MyThread t1 = new MyThread(25); 37 MyThread t2 = new MyThread(25); 38 t1.start(); 39 t2.start(); 40 t1.join(); 41 t2.join(); 42 System.out.println(ThreadDemo.total); 43 } 44}

投稿2024/09/23 04:58

編集2024/09/23 05:21
JavaCommons

総合スコア86

a.com

2024/09/25 01:47

返信遅れました。排他処理についての説明、ありがとうございます!
guest

0

レースコンディションは絶対に起こしてはいけないという前提です

だったら、「起きうるもの」という前提でプログラムを組む一択だと考えます。

投稿2024/09/23 04:54

maisumakun

総合スコア147054

maisumakun

2024/09/23 04:57

「起きないと思っていたら起きた」のではトラブルになりますが、「起きると予想していたけど起きなかった」では、(プログラムを書き換えて他の問題が出る場合を除けば)害はありません。
a.com

2024/09/25 01:48

ありがとうございます。なるほどそういった考え方もあるのですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.29%

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

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

質問する

関連した質問