Javaスレッド – ミューテックスとセマフォの例
Javaマルチスレッドの例では、リソースにアクセスするスレッドの数を制限するために
Semaphore`と
Mutex`を使用する方法を示します。
-
Semaphores
– アクセス可能なスレッドの数を制限する
リソース。例として、ファイルに同時にアクセスするための最大10個の接続を制限する。
-
Mutex
– 一度にリソースにアクセスするスレッドは1つだけです. 例、いつ
クライアントがファイルにアクセスしているときに、他の誰も同じファイルに同時にアクセスする必要はありません。
1.セマフォ
4つのATMを備えたATMキュービクルを考えると、「セマフォ」は4人だけが同時にアクセスできることを確認できます。
SemaphoreTest.java
package com.techfou; import java.util.concurrent.Semaphore; public class SemaphoreTest { //max 4 people static Semaphore semaphore = new Semaphore(4); static class MyATMThread extends Thread { String name = ""; MyATMThread(String name) { this.name = name; } public void run() { try { System.out.println(name + " : acquiring lock..."); System.out.println(name + " : available Semaphore permits now: " + semaphore.availablePermits()); semaphore.acquire(); System.out.println(name + " : got the permit!"); try { for (int i = 1; i <= 5; i++) { System.out.println(name + " : is performing operation " + i + ", available Semaphore permits : " + semaphore.availablePermits()); //sleep 1 second Thread.sleep(1000); } } finally { //calling release() after a successful acquire() System.out.println(name + " : releasing lock..."); semaphore.release(); System.out.println(name + " : available Semaphore permits now: " + semaphore.availablePermits()); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[]args) { System.out.println("Total available Semaphore permits : " + semaphore.availablePermits()); MyATMThread t1 = new MyATMThread("A"); t1.start(); MyATMThread t2 = new MyATMThread("B"); t2.start(); MyATMThread t3 = new MyATMThread("C"); t3.start(); MyATMThread t4 = new MyATMThread("D"); t4.start(); MyATMThread t5 = new MyATMThread("E"); t5.start(); MyATMThread t6 = new MyATMThread("F"); t6.start(); } }
出力は変わることがありますが、ロックと解放のフローは多かれ少なかれ同じでなければなりません。
Total available Semaphore permits : 4 A : acquiring lock... D : acquiring lock... C : acquiring lock... B : acquiring lock... B : available Semaphore permits now: 4 C : available Semaphore permits now: 4 E : acquiring lock... F : acquiring lock... F : available Semaphore permits now: 2 F : got the permit! F : is performing operation 1, available Semaphore permits : 1 D : available Semaphore permits now: 4 A : available Semaphore permits now: 4 D : got the permit! D : is performing operation 1, available Semaphore permits : 0 E : available Semaphore permits now: 2 C : got the permit! B : got the permit! C : is performing operation 1, available Semaphore permits : 0 B : is performing operation 1, available Semaphore permits : 0 F : is performing operation 2, available Semaphore permits : 0 D : is performing operation 2, available Semaphore permits : 0 C : is performing operation 2, available Semaphore permits : 0 B : is performing operation 2, available Semaphore permits : 0 F : is performing operation 3, available Semaphore permits : 0 D : is performing operation 3, available Semaphore permits : 0 C : is performing operation 3, available Semaphore permits : 0 B : is performing operation 3, available Semaphore permits : 0 F : is performing operation 4, available Semaphore permits : 0 D : is performing operation 4, available Semaphore permits : 0 C : is performing operation 4, available Semaphore permits : 0 B : is performing operation 4, available Semaphore permits : 0 D : is performing operation 5, available Semaphore permits : 0 F : is performing operation 5, available Semaphore permits : 0 B : is performing operation 5, available Semaphore permits : 0 C : is performing operation 5, available Semaphore permits : 0 D : releasing lock... F : releasing lock... D : available Semaphore permits now: 1 A : got the permit! A : is performing operation 1, available Semaphore permits : 0 F : available Semaphore permits now: 1 E : got the permit! E : is performing operation 1, available Semaphore permits : 0 B : releasing lock... B : available Semaphore permits now: 1 C : releasing lock... C : available Semaphore permits now: 2 A : is performing operation 2, available Semaphore permits : 2 E : is performing operation 2, available Semaphore permits : 2 A : is performing operation 3, available Semaphore permits : 2 E : is performing operation 3, available Semaphore permits : 2 A : is performing operation 4, available Semaphore permits : 2 E : is performing operation 4, available Semaphore permits : 2 A : is performing operation 5, available Semaphore permits : 2 E : is performing operation 5, available Semaphore permits : 2 A : releasing lock... A : available Semaphore permits now: 3 E : releasing lock... E : available Semaphore permits now: 4
上記の出力を慎重に観察すると、一度に操作を実行する最大4人(C、B、F、D)が存在することがわかり、人々AとEが待機しています。そのうちの1人がロックを解除すると(DとF)、AとEはそれを取得してすぐに再開します。
2.ミューテックス
`ミューテックス`はアクセスカウント1のセマフォーです。銀行でロッカーを使う状況を考えてみましょう。通常、ロッカールームに入ることができるのは1人だけです。
MutexTest.java
package com.techfou; import java.util.concurrent.Semaphore; public class SemaphoreTest { //max 1 people static Semaphore semaphore = new Semaphore(1); static class MyLockerThread extends Thread { String name = ""; MyLockerThread(String name) { this.name = name; } public void run() { try { System.out.println(name + " : acquiring lock..."); System.out.println(name + " : available Semaphore permits now: " + semaphore.availablePermits()); semaphore.acquire(); System.out.println(name + " : got the permit!"); try { for (int i = 1; i <= 5; i++) { System.out.println(name + " : is performing operation " + i + ", available Semaphore permits : " + semaphore.availablePermits()); //sleep 1 second Thread.sleep(1000); } } finally { //calling release() after a successful acquire() System.out.println(name + " : releasing lock..."); semaphore.release(); System.out.println(name + " : available Semaphore permits now: " + semaphore.availablePermits()); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[]args) { System.out.println("Total available Semaphore permits : " + semaphore.availablePermits()); MyLockerThread t1 = new MyLockerThread("A"); t1.start(); MyLockerThread t2 = new MyLockerThread("B"); t2.start(); MyLockerThread t3 = new MyLockerThread("C"); t3.start(); MyLockerThread t4 = new MyLockerThread("D"); t4.start(); MyLockerThread t5 = new MyLockerThread("E"); t5.start(); MyLockerThread t6 = new MyLockerThread("F"); t6.start(); } }
出力は変わることがありますが、ロックと解放の流れは同じでなければなりません。
Total available Semaphore permits : 1 A : acquiring lock... B : acquiring lock... A : available Semaphore permits now: 1 C : acquiring lock... B : available Semaphore permits now: 1 C : available Semaphore permits now: 0 A : got the permit! D : acquiring lock... E : acquiring lock... A : is performing operation 1, available Semaphore permits : 0 E : available Semaphore permits now: 0 D : available Semaphore permits now: 0 F : acquiring lock... F : available Semaphore permits now: 0 A : is performing operation 2, available Semaphore permits : 0 A : is performing operation 3, available Semaphore permits : 0 A : is performing operation 4, available Semaphore permits : 0 A : is performing operation 5, available Semaphore permits : 0 A : releasing lock... A : available Semaphore permits now: 1 B : got the permit! B : is performing operation 1, available Semaphore permits : 0 B : is performing operation 2, available Semaphore permits : 0 B : is performing operation 3, available Semaphore permits : 0 B : is performing operation 4, available Semaphore permits : 0 B : is performing operation 5, available Semaphore permits : 0 B : releasing lock... B : available Semaphore permits now: 1 C : got the permit! C : is performing operation 1, available Semaphore permits : 0 C : is performing operation 2, available Semaphore permits : 0 C : is performing operation 3, available Semaphore permits : 0 C : is performing operation 4, available Semaphore permits : 0 C : is performing operation 5, available Semaphore permits : 0 C : releasing lock... C : available Semaphore permits now: 1 E : got the permit! E : is performing operation 1, available Semaphore permits : 0 E : is performing operation 2, available Semaphore permits : 0 E : is performing operation 3, available Semaphore permits : 0 E : is performing operation 4, available Semaphore permits : 0 E : is performing operation 5, available Semaphore permits : 0 E : releasing lock... E : available Semaphore permits now: 1 D : got the permit! D : is performing operation 1, available Semaphore permits : 0 D : is performing operation 2, available Semaphore permits : 0 D : is performing operation 3, available Semaphore permits : 0 D : is performing operation 4, available Semaphore permits : 0 D : is performing operation 5, available Semaphore permits : 0 D : releasing lock... D : available Semaphore permits now: 1 F : got the permit! F : is performing operation 1, available Semaphore permits : 0 F : is performing operation 2, available Semaphore permits : 0 F : is performing operation 3, available Semaphore permits : 0 F : is performing operation 4, available Semaphore permits : 0 F : is performing operation 5, available Semaphore permits : 0 F : releasing lock... F : available Semaphore permits now: 1
見ることができるように、ここでは一度に1つのスレッドしか実行されません。これはミューテックスの役割です。
参考文献
Javadocs]。
http://stackoverflow.com/questions/771347/what-is-mutex-and-semaphore-in-java-what-is-the-main-difference
[What
Javaではmutexとsemaphoreはありますか?主な違いは何ですか?]。ウィキペディア –
そこにJavaのミューテックス?]。
http://www.oracle.com/technetwork/articles/javase/index-140767.html
[同時
J2SE 5.0によるプログラミング]。
http://www.javaworld.com/article/2076797/java-concurrency/programming-java-threads-in-the-real-world—part-2.html—プログラミング
現実世界のJavaスレッド、第2回]