ロックのサンプルをつくってみた
2006/06/06
2006/11/26
2006-06-23 ここの記事は厳密性に欠けています。
シーケンスが保たれない可能性があります。
こんなのつくってみた。
みそは、try{}finally{}
かならずfinallyを通る。
synchronizedをとると
実行のシーケンス
get lock
a
b
c
release lock
とはならない。
package quicklunch.jeu;
public class TestLock {
Lock lock;
public static void main(String[] args) {
final TestLock testLock = new TestLock();
Runnable runnable = new Runnable() {
public void run() {
try {
while (true) {
testLock.go();
Thread.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
Thread thread3 = new Thread(runnable);
thread1.start();
thread2.start();
thread3.start();
}
public TestLock() {
this.lock = new Lock();
}
public void go() throws InterruptedException {
if (lock.isLocked()) {
return;
}
try {
lock.setLocked(true);
a();
b();
c();
} finally {
lock.setLocked(false);
}
}
public void a() {
System.out.println("process a " + Thread.currentThread());
}
public void b() throws InterruptedException {
System.out.println("process b " + Thread.currentThread());
Thread.sleep(0);
}
public void c() throws InterruptedException {
System.out.println("process c " + Thread.currentThread());
Thread.sleep(0);
//throw new RuntimeException("Wooooo");
}
class Lock {
boolean locked;
public synchronized boolean isLocked() {
return locked;
}
public synchronized void setLocked(boolean locked) {
if (locked) {
System.out.println("get lock!!" + Thread.currentThread());
} else {
System.out.println("release lock!!" + Thread.currentThread());
}
this.locked = locked;
}
}
}
sleepする時間が短いと、synchronizedがどういうふうに効いているかわからなくなる感じがする。
下記は、ロックをとるのと、チェックを同時にさせているので上のソースよりは厳密性がたかまっていると思う。
public class TestLock {
Lock lock;
public static void main(String[] args) {
final TestLock testLock = new TestLock();
Runnable runnable = new Runnable() {
public void run() {
try {
while (true) {
testLock.go();
Thread.sleep(0);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
Thread thread3 = new Thread(runnable);
thread1.start();
thread2.start();
thread3.start();
}
public TestLock() {
this.lock = new Lock();
}
public void go() throws InterruptedException {
if (!lock.lock()) {
return;
}
try {
a();
b();
c();
} finally {
lock.release();
}
}
public void a() {
System.out.println("process a " + Thread.currentThread());
}
public void b() throws InterruptedException {
System.out.println("process b " + Thread.currentThread());
Thread.sleep(10);
}
public void c() throws InterruptedException {
System.out.println("process c " + Thread.currentThread());
Thread.sleep(70);
// throw new RuntimeException("Wooooo");
}
class Lock {
boolean locked;
public synchronized boolean lock() {
if (this.locked) {
return false;
}
System.out.println("get lock!!" + Thread.currentThread());
this.locked = true;
return true;
}
public synchronized void release() {
System.out.println("release lock!!" + Thread.currentThread());
this.locked = false;
}
}
}
シーケンスが保たれない可能性があります。
こんなのつくってみた。
みそは、try{}finally{}
かならずfinallyを通る。
synchronizedをとると
実行のシーケンス
get lock
a
b
c
release lock
とはならない。
package quicklunch.jeu;
public class TestLock {
Lock lock;
public static void main(String[] args) {
final TestLock testLock = new TestLock();
Runnable runnable = new Runnable() {
public void run() {
try {
while (true) {
testLock.go();
Thread.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
Thread thread3 = new Thread(runnable);
thread1.start();
thread2.start();
thread3.start();
}
public TestLock() {
this.lock = new Lock();
}
public void go() throws InterruptedException {
if (lock.isLocked()) {
return;
}
try {
lock.setLocked(true);
a();
b();
c();
} finally {
lock.setLocked(false);
}
}
public void a() {
System.out.println("process a " + Thread.currentThread());
}
public void b() throws InterruptedException {
System.out.println("process b " + Thread.currentThread());
Thread.sleep(0);
}
public void c() throws InterruptedException {
System.out.println("process c " + Thread.currentThread());
Thread.sleep(0);
//throw new RuntimeException("Wooooo");
}
class Lock {
boolean locked;
public synchronized boolean isLocked() {
return locked;
}
public synchronized void setLocked(boolean locked) {
if (locked) {
System.out.println("get lock!!" + Thread.currentThread());
} else {
System.out.println("release lock!!" + Thread.currentThread());
}
this.locked = locked;
}
}
}
sleepする時間が短いと、synchronizedがどういうふうに効いているかわからなくなる感じがする。
下記は、ロックをとるのと、チェックを同時にさせているので上のソースよりは厳密性がたかまっていると思う。
public class TestLock {
Lock lock;
public static void main(String[] args) {
final TestLock testLock = new TestLock();
Runnable runnable = new Runnable() {
public void run() {
try {
while (true) {
testLock.go();
Thread.sleep(0);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
Thread thread3 = new Thread(runnable);
thread1.start();
thread2.start();
thread3.start();
}
public TestLock() {
this.lock = new Lock();
}
public void go() throws InterruptedException {
if (!lock.lock()) {
return;
}
try {
a();
b();
c();
} finally {
lock.release();
}
}
public void a() {
System.out.println("process a " + Thread.currentThread());
}
public void b() throws InterruptedException {
System.out.println("process b " + Thread.currentThread());
Thread.sleep(10);
}
public void c() throws InterruptedException {
System.out.println("process c " + Thread.currentThread());
Thread.sleep(70);
// throw new RuntimeException("Wooooo");
}
class Lock {
boolean locked;
public synchronized boolean lock() {
if (this.locked) {
return false;
}
System.out.println("get lock!!" + Thread.currentThread());
this.locked = true;
return true;
}
public synchronized void release() {
System.out.println("release lock!!" + Thread.currentThread());
this.locked = false;
}
}
}
: