1. 创建一个maven工程
2. 创建加锁解锁类CASlock
package org. example. util;
import sun. misc. Unsafe;
import java. lang. reflect. Field;
public class CASlock {
private volatile int status = 0 ;
private static final Unsafe unsafe = getUnsafe ( ) ;
private static long offset = 0 ;
static {
try {
offset = unsafe. objectFieldOffset ( CASlock. class . getDeclaredField ( "status" ) ) ;
} catch ( NoSuchFieldException e) {
e. printStackTrace ( ) ;
}
}
public void lock ( ) {
while ( ! compareAndSet ( 0 , 1 ) ) {
}
}
public void unlock ( ) {
status = 0 ;
}
public static Unsafe getUnsafe ( ) {
try {
Field field = Unsafe. class . getDeclaredField ( "theUnsafe" ) ;
field. setAccessible ( true ) ;
return ( Unsafe) field. get ( null) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
return null;
}
boolean compareAndSet ( int except, int newValue) {
return unsafe. compareAndSwapInt ( this , offset, except, newValue) ;
}
}
3. 创建测试类LockTest
package org. example. test;
import org. example. util. CASlock;
public class LockTest {
Thread t1;
Thread t2;
CASlock casLock = new CASlock ( ) ;
int k = 0 ;
public void sum ( ) {
casLock. lock ( ) ;
for ( int i = 0 ; i <= 9999 ; i++ ) {
k++ ;
}
casLock. unlock ( ) ;
}
public void start ( ) throws InterruptedException {
t1 = new Thread ( ) {
@Override
public void run ( ) {
sum ( ) ;
}
} ;
t2 = new Thread ( ) {
@Override
public void run ( ) {
sum ( ) ;
}
} ;
t1. start ( ) ;
t2. start ( ) ;
t1. join ( ) ;
t2. join ( ) ;
System. out. println ( "k=" + k) ;
}
public static void main ( String[ ] args) throws InterruptedException {
LockTest test = new LockTest ( ) ;
test. start ( ) ;
}
}
4. 在使用锁的情况下,查看打印结果
k永远等于2000
5. 在不使用锁的情况下,查看打印结果
因为资源竞争的原因,导致k大部分情况都小于2000,极少数情况下等于2000。
6. CAS
compare and swap 比较和交换,在intel的CPU中,使用cmpxchg指令实现; CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。 如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值 。否则,处理器不做任何操作。无论哪种情况,它都会在 CAS 指令之前返回该位置的值;整个过程都是不可打断的,所以CAS是一个原子操作;主要是利用CPU的CAS指令,同时借助JNI来完成Java的非阻塞算法。