ReadWriteLockのサンプル

では、ReadWriteLockのサンプル。
読み込みスレッドは互いにロックせず、書き込みスレッドは他のスレッドとは同時に動かせない、というロックです。
サンプルでは、「か電車」が書き込みスレッド、「電車」が読み込みスレッドです。「か電車」が動くときには他のスレッドは動けません。


ReadWriteLockの実装としては、再入可能なReentrantReadWriteLockが用意されているので、これを使います。

ReadWriteLock lock = new ReentrantReadWriteLock();


実際にロックするときは、ReadWriteLockオブジェクトからwriteLock/readLockメソッドで書き込み用ロックか読み込み用ロックを取得します。

Lock reallock = writer ? lock.writeLock() : lock.readLock();


そうやって取得したロックを、通常のLockオブジェクトと同様にlock/unlockします。

reallock.lock();
reallock.unlock();


ということで、ソース

import java.awt.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.swing.*;

public class ReadWriteLockSample {
    private static ReadWriteLock lock = new ReentrantReadWriteLock();

    public static void main(String args[]) {
        JFrame f = new JFrame("ReadWriteLockサンプル");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(new GridLayout(0, 1));

        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        f.setBounds((screenSize.width-400)/2, (screenSize.height-300)/2, 400, 300);

        for(int i = 0; i < 10; ++i){
            JTextField tf = new JTextField();
            f.add(tf);
            Runner r = new Runner();
            r.tf = tf;
            new Thread(r).start();
        }
        f.setVisible(true);
        
    }

    private static class Runner implements Runnable{
        JTextField tf;
        int speed = (int) (Math.random() * 100 + 50);
        boolean writer = Math.random() < .3;
        @Override
        public void run(){
            try {
                String tr = (writer ? "か" : "") + "電車>";
                for(int i = 0; i < 50; ++i){
                    tf.setText(tr);
                    tr = " " + tr;
                    Thread.sleep(speed);
                }
                Lock reallock = writer ? lock.writeLock() : lock.readLock();
                try{
                    reallock.lock();
                    for(int i = 0; i < 50; ++i){
                        tf.setText(tr);
                        tr = " " + tr;
                        Thread.sleep(speed);
                    }
                }finally{
                    reallock.unlock();
                }
            } catch (InterruptedException ex) {
            }
        }
    }

}