next up previous
Next: 12.4 synchronizedメソッド Up: 12 同期処理 Previous: 12.2 排他(mutual exclusion)制御

12.3 synchronizedブロック

きわどい領域に対して同期をとるためのブロック文が 用意されている. きわどい領域をexprとすれば

     synchronized (expr) {
        statements
     }
という記述になる. 配列へのアクセス制御の例として,

public static void abs(int[] values) {

    synchronized (values) {
        for (int i = 0;
             i < values.length; i++) {
            if (values[i] < 0)
                values[i] = -values[i];
        }
    }
}
とする. synchronized文によってvalues配列に対して 同様に同期をとっている他のコードから実行中に 配列が変更されることがないということが保証される. このような同期は,クライアント側同期(client-side synchronization) と呼ばれる.共有されるオブジェクトを操作する前に, そのオブジェクトで同期をとることをすべてのクライアントが合意する.

// synchronize2.java
class synchronize2
{
    public static void main(String args[])
    {
        Shared shared = new Shared();

        CustomThread5 thread1 =
            new CustomThread5(shared, "one");
        CustomThread5 thread2 =
            new CustomThread5(shared, "two");
        CustomThread5 thread3 =
            new CustomThread5(shared, "three");
        CustomThread5 thread4 =
            new CustomThread5(shared, "four");

        try {
            thread1.join();
            thread2.join();
            thread3.join();
            thread4.join();
        } catch(InterruptedException e) {}
    }
}

class CustomThread5 extends Thread
{
    Shared shared;

    public
    CustomThread5(Shared shared, String string)
    {
        super(string);
        this.shared = shared;
        start();
    }

    public void run() {
        synchronized(shared) {
            shared.
                doWork(Thread.
                       currentThread().getName());
        }
    }
}

class Shared
{
    void doWork(String string)
    {
        System.out.println("Starting "
                           + string);

        try {
            Thread.sleep((long)
                         (Math.random() * 500));
        } catch (InterruptedException e) {}

        System.out.println("Ending " + string);
    }
}
実行結果は以下のようになる.

% java synchronize2
Starting one
Ending one
Starting two
Ending two
Starting three
Ending three
Starting four
Ending four
Java言語は,スレッドセーフな言語で型longとdouble以外の変数への 読み書きはアトミックであることを保証している. つまり,変数は,スレッドにより書かれた値を保持していて,異なる書き込みに より混ぜ合わされた値の一部を持つことはない. アトミックな変数ではそれらのスレッド間の干渉が起こらない ために,同期をとる必要はない.

generated through LaTeX2HTML. M.Inaba 平成18年5月7日