Use AtomicReference to implement Reentrant Lock - Java Thread

Java examples for Thread:Lock

Description

Use AtomicReference to implement Reentrant Lock

Demo Code

import java.util.concurrent.atomic.AtomicReference;

interface SpinLock {
  public void lock();

  public void unlock();
}

public class Main {

  private static class NonReentrantSpinLock implements SpinLock {

    private AtomicReference<Thread> owner = new AtomicReference<Thread>();

    public void lock() {
      Thread currentThread = Thread.currentThread();

      while (!owner.compareAndSet(null, currentThread)) {

      }/*ww w  .j  a  v  a  2  s  .c om*/
    }

    public void unlock() {
      Thread currentThread = Thread.currentThread();
      owner.compareAndSet(currentThread, null);
    }
  }

  private static class ReentrantSpinLock implements SpinLock {
    private AtomicReference<Thread> owner = new AtomicReference<Thread>();

    private int count = 0;

    public void lock() {
      Thread currentThread = Thread.currentThread();
      if (currentThread == owner.get()) {
        count++;
        return;
      }
      while (!owner.compareAndSet(null, currentThread)) {

      }
    }

    public void unlock() {
      Thread currentThread = Thread.currentThread();

      if (currentThread == owner.get()) {
        if (count != 0) {
          count--;
        } else {
          owner.compareAndSet(currentThread, null);
        }
      }
    }
  }

  private static class ReentrantTestDemo {
    private SpinLock lock;

    private int i = 0;

    public ReentrantTestDemo(SpinLock lock) {
      this.lock = lock;
    }

    public void write(int delta) {
      try {
        if (lock != null) {
          lock.lock();
        }
        i = i + delta;
        System.out.println("Start write1..." + i);
        Thread.currentThread().sleep(300l);
        i = i + delta;
        System.out.println("End write1..." + i);
        Thread.currentThread().sleep(500l);
        i = i + delta;
        System.out.println("End write2..." + i);

        write0(delta);
      } catch (Exception e) {

      } finally {
        if (lock != null) {
          lock.unlock();
        }
      }

    }

    public void write0(int delta) {
      try {
        if (lock != null) {
          lock.lock();
        }
        i = i + delta;
        System.out.println("Start write1..." + i);
        Thread.currentThread().sleep(300l);
        i = i + delta;
        System.out.println("End write1..." + i);
        Thread.currentThread().sleep(500l);
        i = i + delta;
        System.out.println("End write2..." + i);
      } catch (Exception e) {

      } finally {
        if (lock != null) {
          lock.unlock();
        }
      }

    }
  }

  private static class WriteTask implements Runnable {

    private ReentrantTestDemo demo;

    private int delta;

    public WriteTask(ReentrantTestDemo demo, int delta) {
      this.delta = delta;
      this.demo = demo;
    }

    @Override
    public void run() {
      demo.write(delta);
    }
  }

  private void testLock(SpinLock lock) {
    System.out.println("test lock---");
    ReentrantTestDemo demo = new ReentrantTestDemo(lock);
    Thread t1 = new Thread(new WriteTask(demo, 1));
    t1.setName("t1");
    Thread t2 = new Thread(new WriteTask(demo, 3));
    t2.setName("t2");
    Thread t3 = new Thread(new WriteTask(demo, 7));
    t3.setName("t3");
    t1.start();
    t2.start();
    t3.start();
  }

  public static void main(String[] args) {
    Main test = new Main();
    // test.testLock(null);
    test.testLock(new NonReentrantSpinLock());
    // test.testLock(new ReentrantSpinLock());
  }

}

Related Tutorials