Geekroid-ギークロイド(仮)|ITエンジニアの日常をささいな情報で彩るコラム

ITエンジニアの転職

ReentrantLockクラス

明示的にロックを獲得する – ReentrantLockクラス
public void lock()
public void unlock()
regex:正規表現
flags:検索オプション
input:入力文字列

synchronizedブロックによる同期は、アプリ開発者がロックの獲得/解除を意識しなくても良いことから「暗黙的なロック」と呼ばれます。対して、メソッドを跨る処理などで「明示的に」ロックを獲得/解除したい場合があります。この場合、ReentrantLockクラス(java.util.concurrent.locksパッケージ)を利用します。
ReentrantLockクラスではlockメソッドで明示的にロックを獲得した後、unlockメソッドで解除する必要があります。
以下は、synchronized修飾子の項のサンプル(incrementメソッド)をReentrantLockクラスで書き換えたものです。

LockSample.java

package com.example.mynavi.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockSample {
  private int count;
  private final Lock lock = new ReentrantLock();

  public static void main(String[] args) {
    LockSample ls = new LockSample();
    ls.execute();
  }

  public void execute() {
    final int THREAD_MAX = 300000;
    Thread[] ts = new Thread[THREAD_MAX];
    for (int i = 0; i < THREAD_MAX; i++) {
      ts[i] = new Thread(new MyThread(this));
      ts[i].start();
    }
    for (int i = 0; i < THREAD_MAX; i++) {
      try {
        ts[i].join();
      } catch (InterruptedException e) {
        System.out.println(e);
      }
    }
    System.out.println(count);
  }

  public void increment() {
    lock.lock();
    try {
      this.count++;
    } finally {
      lock.unlock();
    }
  }

  private static class MyThread implements Runnable {
    private LockSample _counter;

    public MyThread(LockSample counter) {
      this._counter = counter;
    }

    @Override
    public void run() {
      _counter.increment();
    }
  }
}

ReentrantLockクラスでlockメソッドを利用した場合には、その直後からtryブロックで括るのを忘れないようにしてください。これは処理中に思わぬ例外が発生した場合にも、finally句でunlockメソッドが呼び出されることを保証するためです。

関連ページ
synchronized

スレッド
Threadクラス/Runnableインターフェイス
synchronized修飾子/ブロック
ReentrantLockクラス
AtomicXxxxxクラス
Executorsクラス

Geekroid-ギークロイド(仮)|ITエンジニアの日常をささいな情報で彩るコラム

ITエンジニアの転職