スレッドの排他制御|Javaから楽しく学ぶ!ゲームプログラミング専門学校

Javaから楽しく学ぶ!ゲームプログラミング専門学校

ゲームプログラミングとはその名のとおりゲームのプログラムを作ることを指します。『Javaから楽しく学ぶ!ゲームプログラミング専門学校』ではゲームプログラミングについて、実際にゲームプログラムをJAVAプログラミング言語を使用し、作成していきながら詳しく解説していきます。

スレッドの排他制御

スレッドを複数持つことで、「同時に複数の処理を実行する」ということができ、作成できるプログラムの実現可能性が広がるわけですが、「同時に複数の処理を実行する」ことでときに、プログラムが意図しない動作をしてしまうことがあります。

例えば、同じインスタンスの同じフィールドを、複数のスレッドが同時に使用したらどうなるでしょうか。
public class CarRun implements Runnable{
private String carName;
private int count;

public CarRun(String carName){
this.carName = carName;
}

public static void main(String[] args){
CarRun car1 = new CarRun("インサイト");

Thread th1 = new Thread(car1);
Thread th2 = new Thread(car1);
th1.start();
th2.start();

}

public void run(){
count = 0;
for(int i = 0; i < 5; i++){
try{
Thread.sleep(1000);
}catch(Exception e){}
this.addCount();
System.out.println(carName + " : " + count + "回目の処理です。");
}
}

public void addCount(){
count += 1;

}
}

前回のサンプルを少し改良したのが上記サンプルです。
        CarRun car1 = new CarRun("インサイト");

Thread th1 = new Thread(car1);
Thread th2 = new Thread(car1);
th1.start();
th2.start();

上記では同じインスタンス(car1)でスレッドを二つ起動させています。

私の環境で実行した結果は下記のようになりました。

インサイト : 1回目の処理です。
インサイト : 1回目の処理です。
インサイト : 2回目の処理です。
インサイト : 3回目の処理です。
インサイト : 4回目の処理です。
インサイト : 5回目の処理です。
インサイト : 6回目の処理です。
インサイト : 7回目の処理です。
インサイト : 8回目の処理です。
インサイト : 9回目の処理です。


for文のループ回数は5回と設定しているのに、9回も処理しています。
おかしいように見えるかもしれませんが、2つのスレッドが同時に進行し、同じインスタンス変数を加算していっているわけですから、5回以上処理するのは自然な結果です。
しかし、だとすると10回加算処理されければならないのに9回しか処理してません。
つまり、1回分の加算処理が正しく行われていないことになります。

では、下記のサンプルを実行したらどうなるでしょう。
public class CarRun implements Runnable{
private String carName;
private int count;

public CarRun(String carName){
this.carName = carName;
}

public static void main(String[] args){
CarRun car1 = new CarRun("インサイト");

Thread th1 = new Thread(car1);
Thread th2 = new Thread(car1);
th1.start();
th2.start();

}

synchronized public void run(){
count = 0;
for(int i = 0; i < 5; i++){
try{
Thread.sleep(1000);
}catch(Exception e){}
this.addCount();
System.out.println(carName + " : " + count + "回目の処理です。");
}
}

public void addCount(){
count += 1;

}
}

【実行結果】
インサイト : 1回目の処理です。
インサイト : 2回目の処理です。
インサイト : 3回目の処理です。
インサイト : 4回目の処理です。
インサイト : 5回目の処理です。
インサイト : 1回目の処理です。
インサイト : 2回目の処理です。
インサイト : 3回目の処理です。
インサイト : 4回目の処理です。
インサイト : 5回目の処理です。


2つスレッドを起動したはずですが、スレッドが一つずつ処理されているのがわかると思います。

上記2つのサンプルの違いはsynchronizedをrun()メソッドに加えただけです。

次回、スレッドの排他制御についてもう少し詳しく見ていきます。
トラックバック:0Edit
Copyright © Javaから楽しく学ぶ!ゲームプログラミング専門学校 All Rights Reserved.
当サイトのテキストや画像等すべての転載転用・商用販売を固く禁じます