Coins Java - Experiment11

モニタの獲得と開放

[Coins Java - Experiment]

目的

作業

まず、nativeメソッドからモニタに入るためのクラスを準備する。

$ emacs NativeLock.java
--- NativeLock.java
public class NativeLock implements Runnable {

    private final Object lock;

    public NativeLock(Object lock) {
        this.lock = lock;
    }

    public native void run();
}
---
$ gcj -C NativeLock.java
$ gcjh NativeLock

以下の2つの関数を利用してモニタを取得/開放する。モニタを取得したら、5秒ほど停止する。

$ emacs natNativeLock.cc
--- natNativeLock.cc
#include <stdio.h>

#include <java/lang/Thread.h>
#include <java/lang/System.h>
#include "NativeLock.h"

void NativeLock::run () {

  printf("NativeLock : try to enter on %lld\n", ::java::lang::System::currentTimeMillis()/1000);

  _Jv_MonitorEnter(this->lock);
  {
    printf("NativeLock : lock on %lld\n", ::java::lang::System::currentTimeMillis()/1000);
    ::java::lang::Thread::sleep(5000);
    printf("NativeLock : unlock on %lld\n", ::java::lang::System::currentTimeMillis()/1000);
  }
  _Jv_MonitorExit(this->lock);
}
---
$ gcc -c natNativeLock.cc

次は、gcjのメソッドからモニタに入るためのクラスを用意する。先ほど同様、モニタを取得したら5秒ほど停止する。

$ emacs GcjLock.java
--- GcjLock.java
public class GcjLock implements Runnable {

    private final Object lock;

    public GcjLock(Object lock) {
        this.lock = lock;
    }

    public void run() throws Exception {
        System.out.println("GcjLock : try to enter on " + System.currentTimeMillis()/1000);

        synchronized(lock) {
            System.out.println("GcjLock : lock on " + System.currentTimeMillis()/1000);
            Thread.sleep(5000);
            System.out.println("GcjLock : unlock on " + System.currentTimeMillis()/1000);
        }
    }
}
---
$ gcj -C GcjLock.java

先ほど作成した2つのプログラムを、スレッドで同時に実行するためのクラスを作る。

$ emacs Start.java
--- Start.java
public class Start {

    public static void main(String[] args) {
        Object lock = new Object();

        new Thread(new NativeLock(lock)).start();
        new Thread(new GcjLock(lock)).start();
    }
}
---
$ gcj -C Start.java

コンパイル

$ gcj --main=Start *.class *.o

結果

以下のようになった。

$ ./a.out
NativeLock : try to enter on 1078900985
NativeLock : lock on 1078900985
GcjLock : try to enter on 1078900985
NativeLock : unlock on 1078900990
GcjLock : lock on 1078900990
GcjLock : unlock on 1078900995

それぞれ5秒ずつ、排他的にロックをかけていることを確認できる。

考察

CNIでは、変数のスコープとデストラクタを使用して、安全にモニタを開放するようにしている。

Copyright (C) 2002-2006 s.arakawa