JavaのStampedLockクラスについて


練習のために学習したJava8のStampedLockクラスについて記述します。但し一部のメソッドについてのみ言及します。
---

基本(##)
---
このクラスには３つのモードが存在し、各モードを操作することによりメソッドのアクセスに制限を設けることができます。そして、各モードの操作にはstampというものを使用します。stampというのは整数で、long型で使用します。

<b>Writing</b>-

 - writeLock()メソッド・・・排他的にアクセスをブロックする。戻り値：スタンプ
 - unlockWrite(long)メソッド・・・上記ブロックの解除。
 
 
<b>Reading</b>-

- ReadLock()メソッド・・・排他的ではなくアクセスをブロックする。戻り値：スタンプ

- unlockRead(long stamp)メソッド・・・上記ブロックの解除。


<b>Optimistic Reading</b>-

- tryOptimisticRead()メソッド・・・排他的ロックが掛かっていれば0を返す。それ以外の場合はstampを返す。

- validate(long stamp)メソッド・・・ロックがかかっていなければtrueを返す。スタンプが0ならfalseを返す。

　公式のドキュメントによると、このモードは脆弱で、writingモードでアクセス可能なため、readフィールドに限定して使用すべきとされています。
　上記の各モードには、upgradeのためのconvertメソッドがあります。

<b>tryConvetToWriteLock(long stamp)</b>-
　もしwrite lockがかかっていればstampを返し、read lockがかかっていてwrite lockがかかっていなければread lockを解除しwrite lockをかけstampを返す。もしoptimistic readの状態ですぐにアクセス可能であればwrite stampを返す。上記以外の場合は0を返す。

<b>tryConvetToReadLock(long stamp)</b>-
　write lockがかかっていれば解除しread lockを掛ける。read lockがかかっていればstampを返す。optimistic readがかかっており、すぐにread lockが掛けられるならread lockをかけstampを返す。上記以外の場合は0を返す。

<b>tryConvetToOptimisticRead(long stamp)</b>-
　もし何かしらのlockがかかっていればそれを解除しoptimistic read stampを返す。optimistic read状態であればそのstampを返す。上記以外の場合は0を返す。


StampedLocksはマルチスレッドで利用する場合に有効なクラスです。使用するstampは一年以上オペレーションが継続すれば再利用されます。LockがかかっているかどうかはisReadLock(),isWriteLock(),getReadLockCount()で確認することができます。
　

```Main.java
public class Main{
 public static void main(String[] args){

  StampledLockTest stampledLockTest = new StampledLockTest();

  testThread testThread = new testThread();

  testThread.start();

  testThread.run();
 }
}

```

```testThread.java
public class testThread extends Thread{
 StampledLockTest stampledLockTest = new StampledLockTest();

 testThread(){}

 public void run(){
  for(int i=0; i<10; i++){
   stampledLockTest.writeLockTest();
   //stampledLockTest.readLockTest();
   try{
      sleep(100);
   }catch(InterruptedException e){
      e.printStackTrace();
   }
   }
  }
 }
}

```

```StampledLockTest.java

import java.util.concurrent.locks.StampedLock;

public class StampledLockTest{
 public static void main(String[] args){

  StampedLock sLock  = new StampedLock();
  long time = System.currentTimeMills();
 
  public int number;
  public StampledLockTest() {this.number=0;}

  public void writeLockTest(){

		long stamp = sLock.writeLock();

		number++;

		sLock.unlockWrite(stamp);

		System.out.println(number);
	}

  public void readLockTest(){

		long stamp = sLock.readLock();
                System.out.println(System.currentTimeMillis()-time+"time");
		number++;
                System.out.println(System.currentTimeMillis()-time+100+"time");
		sLock.unlockRead(stamp);
                System.out.println(System.currentTimeMillis()-time+1000+"time");
		System.out.println(number);
	}

 }
}
```


上記のコードでwriteLockを使用したwriteLockTestメソッドを実行すると下記の結果が得られました。


```javaw.exe
>1
>2
>3
>4
>5
>6
>7
>8
>9
>10
>11
>12
>13
>14
>15
>16
>17
>18
>19
>20
```


そして、testThread.javaクラスのrunメソッド内のwriteLockTestの行をコメント化してreadLockTestの行のコメントを外すと下記の結果が得られました。

```javaw.exe
>0time
>0time
>100time
>1000time
>2
>0time
>100time
>1000time
>3
>0time
>100time
>1000time
>4
>100time
>1time
>1001time
>5
>1time
>101time
>101time
>1001time
>6
>1001time
>6
>1time
>1time
>101time
>101time
>1001time
>8
>1001time
>8
>1time
>1time
>101time
>101time
>1001time
>10
>1001time
>10
>1time
>101time
>1001time
>11
>1time
>1time
>101time
>101time
>1001time
>13
>1time
>101time
>1001time
>14
>1001time
>14
>2time
>102time
>1002time
>15
>2time
>2time
>102time
>102time
>1002time
>17
>1002time
>17
>2time
>2time
>102time
>102time
>1002time
>19
>1002time
>19
>2time
>102time
>1002time
>20
```

上記の結果から、writeLockメソッドを使用した場合は、次のアクセスがあった場合Lockが解除されるまでそれ以降の全てのコードが実行されませんが、readLockメソッドの場合は、次のアクセスがあっても２つの処理が並行して行われます。しかしメソッド内の実行順序はバラバラで私のレベルでは理解はできませんでした。中途半端ですが今回の記事はここまでとします。


参照リンク(##)
---
[https://docs.oracle.com/javase/8/docs/api/](https://docs.oracle.com/javase/8/docs/api/)