プログラマメモ2 - programmer no memo2

プログラマメモ: ロックのサンプルをつくってみた 2006/06/23
2006/11/26

プログラマメモ: ロックのサンプルをつくってみた



以前書いた記事への補完です。

適当にアップしてます。

#どこかの機会できちんとまとめたいです。



より厳密にスレッドの実験を行う場合は、

Thread.yield();

を使うといいようです。





「ほとんどのプログラマによるThread.yieldの唯一の使い方は、テスト中にプログラムの平行性を意図的に増加させることです。」

「Effective Java」P.194





とありました。





会社でJavaに詳しい人に教えていただきました。



より厳密に動作するようにしてみました。

絶対要件

処理のa b cと決まった順序で実行されることを保証することです。





public class TestThread_synchronized_block {



Lock lock;



public static void main(String[] args) {



final TestThread_synchronized_block testLock = new TestThread_synchronized_block();



new Thread(createRunnable(testLock)).start();

new Thread(createRunnable(testLock)).start();

new Thread(createRunnable(testLock)).start();



}



public static Runnable createRunnable(final TestThread_synchronized_block th) {

return new Runnable() {

public void run() {

try {

while (true) {

th.go();

Thread.sleep(10);

}

} catch (InterruptedException e) {

e.printStackTrace();

}

}

};



}



public TestThread_synchronized_block() {

this.lock = new Lock();

}



int checkCont = 0;



public void go() throws InterruptedException {

if (!lock.lock()) {

return;

}

try {

Thread.yield(); // (1) ここで他スレッドに処理が移る

a();

Thread.yield(); // (2) ここで他スレッドに処理が移る

b();

Thread.yield(); // (3) ここで他スレッドに処理が移る

c();

Thread.yield(); // (4) ここで他スレッドに処理が移る

if (checkCont == 3) {

System.out.println("not broken!!");

} else {

System.out.println("BROKEN!!");

System.exit(0);

}

} finally {

checkCont = 0;

lock.release();

}



}



public void a() throws InterruptedException {

System.out.println(" process a " + Thread.currentThread());

checkCont++;

}



public void b() throws InterruptedException {

System.out.println(" process b " + Thread.currentThread());

checkCont++;

}



public void c() throws InterruptedException {

System.out.println(" process c " + Thread.currentThread());

checkCont++;

}



class Lock {



private boolean locked = false;



public boolean lock() {

/*

* using synchronized block

*/

synchronized (this) {

if (locked) {

return false;

}

locked = true;



return true;

}



}



public void release() {

/*

* using synchronized block

*/

synchronized (this) {

this.locked = false;

}

}



}



}







厳密に動く別バージョンです。





public class TestThread_another_version {

private volatile Lock lock = new Lock();



public static void main(String[] args) {

final TestThread_another_version testLock = new TestThread_another_version();

new Thread(createRunnable(testLock)).start();

new Thread(createRunnable(testLock)).start();

new Thread(createRunnable(testLock)).start();

}



public static Runnable createRunnable(final TestThread_another_version th) {

return new Runnable() {

public void run() {

try {

while (true) {

th.go();

Thread.sleep(3);

}

} catch (InterruptedException e) {

e.printStackTrace();

}

}

};



}



public TestThread_another_version() {

}

int checkCont = 0;

public void go() throws InterruptedException {

if (lock.tryLock()) {

try {

Thread.yield();

a();

Thread.yield();

b();

Thread.yield();

c();

Thread.yield();

if (checkCont == 3) {

System.out.println("not broken!!");

} else {

System.out.println("BROKEN!!");

System.exit(0);

}

}

finally {

checkCont = 0;

lock.unLock();

}

}

}



public void a() throws InterruptedException {

System.out.println (" process a " + Thread.currentThread());

checkCont++;

}



public void b() throws InterruptedException {

System.out.println(" process b " + Thread.currentThread ());

checkCont++;

}



public void c() throws InterruptedException {

System.out.println(" process c " + Thread.currentThread());

checkCont++;

}



private static final class Lock {

public synchronized boolean tryLock() {

Thread.yield();

if (locked) {

Thread.yield();

return false;

} else {

Thread.yield();

locked = true;

Thread.yield();

return true;

}

}



public void unLock() {

Thread.yield();

locked = false;

Thread.yield();

}



private volatile boolean locked;

}

}





NYSLのもといただいたコードです。





public final class TestThread_4 {

public static void main(String[] args) {

final TestThread_4 testLock = new TestThread_4();

for (int i = 0, n = 10; i < n; ++i) {

new Thread(createRunnable(testLock)).start();

}

}



public static Runnable createRunnable(final TestThread_4 testThread_4) {

return new Runnable() {

public void run() {

while (true) {

testThread_4.go();

}

}

};

}



public void go() {

Thread.yield();

if (lock.tryLock()) {

try {

Thread.yield();

a();

Thread.yield();

b();

Thread.yield();

c();

Thread.yield();

}

finally {

lock.unLock();

}

}

}



public void a() {

System.out.println(" process a " + Thread.currentThread() + ": " + this.toString());

}



public void b() {

System.out.println(" process b " + Thread.currentThread() + ": " + this.toString());

}



public void c() {

System.out.println(" process c " + Thread.currentThread() + ": " + this.toString());

}



private static final class Lock {

public synchronized boolean tryLock() {

if (locked) {

return false;

} else {

locked = true;

return true;

}

}



public synchronized void unLock() {

locked = false;

}



private volatile boolean locked;

}



private volatile Lock lock = new Lock();

}



: