リファクタリングのためコードを見てたら
何回か見て忘れてしまったものが出たので忘れないようにメモしました。
synchronized とは?
synchronized
とは排他制御のことで、
排他制御=複数のプロセス(またはスレッド)が同時に入ることを防ぐことである
らしいです。
試してみる
言葉だけだとしっくり来なかったので
直接試してみました。
前提のイメージとして、
家族が一人ずつお風呂に入るイメージです。
(一人が終わるまで入ってはいけません。)
「メインメソッドのあるメインクラス」
MainClass.java
public class MainClass {
public static void main(String[] args) {
Bathroom bathroom = new Bathroom();
FamilyTread father = new FamilyTread(bathroom, "父");
FamilyTread mother = new FamilyTread(bathroom, "母");
FamilyTread sister = new FamilyTread(bathroom, "姉");
FamilyTread me = new FamilyTread(bathroom, "私");
father.start();
mother.start();
sister.start();
me.start();
}
}
「Thread
を継承した家族に対するクラス」
FamilyTread.java
class FamilyTread extends Thread {
private Bathroom mBathroom;
private String mName;
FamilyTread(Bathroom bathroom, String name) {
this.mBathroom = bathroom;
this.mName = name;
}
public void run() {
mBathroom.openDoor(mName);
}
}
「家族クラスから呼ばれて作業をするクラス」
class Bathroom {
void openDoor(String name) {
System.out.println(name + "「お風呂に入ります!」");
for (int count = 0; count < 100000; count++) {
if (count == 1000) {
System.out.println(name + "「お風呂に入りました。」");
}
}
System.out.println(name + "「お風呂から出ました!」");
}
}
何回か実行した結果
父がまだお風呂に入ってるのに...!
順番がめちゃくちゃになってしまいました。(たまたま正しい順番になったりもします)
そこでsynchronized
を使うとお風呂(スレッド)に同時に入ることを防ぐことができると。
synchronized を使ってみる
Bathroom
クラスの openDoor
メソッドに synchronized
をつけてみました。
class Bathroom {
synchronized void openDoor(String name) {
System.out.println(name + "「お風呂に入ります!」");
for (int count = 0; count < 100000; count++) {
if (count == 1000) {
System.out.println(name + "「お風呂に入りました。」");
}
}
System.out.println(name + "「お風呂から出ました!」");
}
}
結果
ちゃんとひとりづつ入るようになりました!
参照