关于Java的StampedLock类
我将描述学习Java 8的StampedLock类,这是为了练习而学习的。但我只提及其中的一些方法。
基本(#1)
这个类有三种模式,并且可以通过操作每个模式来限制方法的访问。而操作每个模式使用了一个叫做”stamp”的东西。”stamp”是一个整数,使用long类型。
写作
-
- writeLock()メソッド・・・排他的にアクセスをブロックする。戻り値:スタンプ
- unlockWrite(long)メソッド・・・上記ブロックの解除。
阅读
-
- ReadLock()メソッド・・・排他的ではなくアクセスをブロックする。戻り値:スタンプ
- unlockRead(long stamp)メソッド・・・上記ブロックの解除。
乐观阅读
-
- tryOptimisticRead()メソッド・・・排他的ロックが掛かっていれば0を返す。それ以外の場合はstampを返す。
- validate(long stamp)メソッド・・・ロックがかかっていなければtrueを返す。スタンプが0ならfalseを返す。
根据公式文件,该模式被认为是脆弱的,并且只能通过writing模式来访问。建议仅将其用于read字段。
对于上述每个模式,都有一个用于升级的转换方法。
尝试将其转换为写锁(tryConvetToWriteLock) – 如果已经有写锁,则返回stamp;如果有读锁但没有写锁,则解锁读锁并加上写锁,然后返回stamp;如果处于乐观读状态且立即可以访问,则返回写stamp;否则返回0。
如果有写锁被获取到,则解除该写锁并获取读锁。如果有读锁被获取到,则返回 stamp。如果有乐观读锁被获取到,并且可以立即获取读锁,则获取读锁并返回 stamp。除以上情况外,则返回 0。
尝试转换为乐观读取(long stamp)-
如果有任何锁定存在,则释放该锁定并返回乐观读取的时间戳。如果处于乐观读取状态,则返回该时间戳。如果不符合以上情况,则返回0。
StampedLock是一個有效的類別,當用於多線程時時非常有用。如果應用程序運行超過一年,則可以再次使用當前stamp。可以通過isReadLock(),isWriteLock()和getReadLockCount()進行確認是否有鎖定。
public class Main{
public static void main(String[] args){
StampledLockTest stampledLockTest = new StampledLockTest();
testThread testThread = new testThread();
testThread.start();
testThread.run();
}
}
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();
}
}
}
}
}
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);
}
}
}
使用上述的代码运行writeLockTest方法并使用writeLock,得出以下结果。
>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行的注释时,得到了以下结果。
>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方法时,即使有下一次访问,两个操作仍会并行进行。但方法内的执行顺序是随机的,我在我的水平上无法理解。虽然不完整,但本文到此为止。
请参阅链接(##)。
以下是Java官方文档的链接:https://docs.oracle.com/javase/8/docs/api/