[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[jfriends-ml 12796] Re: 読書会 (Java 言語仕様第3版) 第 10 回議 事録



高橋(徹)です。

TAKAHASHI, Tomohiro wrote:

>   JavaVMやThreadを特定のCPUやCoreに割り付ける件ですが、
:[中略]
>   [Concurrency - Java and Multicore]
>     http://forum.java.sun.com/thread.jspa?threadID=5153516
ここに記載されていた、Windows上でstartコマンドの/AFFINITYオプション
による方法は簡単です。でも以下URLの記事によればWindows Vistaのみ
のようです。(以下記事には他の方法の記載あり)
http://www.atmarkit.co.jp/fwin2k/win2ktips/862affinity/affinity.html

RuntimeクラスのavailableProcessors()メソッドで、そのJavaVMで利用可能な
CPUの数が取得できます。
以下、2つのスレッドが共有するvolatile変数を非アトミックにインクリメント
する実験コード(ソース添付)の実行結果です。
実行環境:
 CPU: AMD Athlon 64x2(デュアルコア)
 OS: Windows Vista (x64)
 JavaVM: JDK1.6.0_04 (64bit)

C:\work> start java SharedVolatileCounterIncrementor
Available CPUs is 2
I have incremented 85599223 times
I have incremented 91841073 times
Shared counter is 105359768

C:\work>start /AFFINITY 1 java SharedVolatileCounterIncrementor
Available CPUs is 1
I have incremented 247873783 times
I have incremented 247560305 times
Shared counter is 484036212

CPU1個では共有変数の値がほぼ各スレッドがインクリメントした数の合計に
近い値になっています。
ちなみに、CPU1個の方が単位時間あたりのインクリメント数が多くなって
おり、興味深い現象です。(キャッシュ・コヒーレントが関係するのかな?)

public class SharedVolatileCounterIncrementor implements Runnable {
    private volatile int counter;

    public void run() {
        int numIncremented = 0;
        while (true) {
            counter++;
            numIncremented++;
            if (Thread.currentThread().isInterrupted()) {
                System.out.printf("I have incremented %d times%n",
                                  numIncremented);
                return;
            }
        }
    }

    public final static void main(final String[] args) throws Exception {
        System.out.println("Available CPUs is " + Runtime.getRuntime().availableProcessors());
        SharedVolatileCounterIncrementor sci =
            new SharedVolatileCounterIncrementor();
        Thread t1 = new Thread(sci);
        Thread t2 = new Thread(sci);
        t1.start();
        t2.start();
        Thread.sleep(10000);
        t1.interrupt();
        t2.interrupt();
        t1.join();
        t2.join();
        System.out.println("Shared counter is " + sci.counter);
        System.in.read();
    }
}