1 CAS
1.1 基本介绍
Compare And Set,直译过来就是比较并设值,解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数—内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。
/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
1.2 案例
public static void main(String[] args) {
//期望12,设置为20
AtomicInteger atomicInteger=new AtomicInteger(10);
boolean b = atomicInteger.compareAndSet(12, 20);
System.out.println(b);
System.out.println(atomicInteger.get());
System.out.println("#######################");
//期望10,设置为20
AtomicInteger atomicInteger1=new AtomicInteger(10);
boolean b1 = atomicInteger1.compareAndSet(10, 20);
System.out.println(b1);
System.out.println(atomicInteger1.get());
}
2 Unsafe
2.1 简介
Java 不能直接访问操作系统底层,而是通过本地方法来访问。Unsafe 类提供了硬件级别的原子操作。Unsafe 类在 sun.misc 包下,不属于 Java 标准。很多 Java 的基础类库,包括一些被广泛使用的高性能开发库都是基于 Unsafe 类开发,比如 Netty、Hadoop、Kafka 等。
(1) Unsafe 是用于在实质上扩展 Java 语言表达能力、便于在更高层(Java 层)代码里实现原本要在更低层(C 层)实现的核心库功能用的。
(2) 这些功能包括裸内存的申请/释放/访问,低层硬件的 atomic/volatile 支持,创建未初始化对象等。
(3) 它原本的设计就只应该被标准库使用,因此不建议在生产环境中使用。
2.2 获取Unsafe
public final class UnsafeUtils {
private UnsafeUtils() {
}
/**
* 获取Unsafe
*/
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;
}
}
3 Unsafe实现CAS锁
3.1 接口
public interface Counter {
void increment();
long getCounter();
}
3.2 CasCounter
public class CasCounter implements Counter {
private volatile long counter = 0;
private Unsafe unsafe;
private long offset;
public CasCounter() throws Exception {
//获取unsafe
unsafe = UnsafeUtils.getUnsafe();
//设置偏移量为counter
offset = unsafe.objectFieldOffset(CasCounter.class.getDeclaredField("counter"));
}
@Override
public void increment() {
long current = counter;
/**
* compareAndSwapLong(Object var1, long var2, long var4, long var6)
* var1:对象,var2:偏移量,var4:expect(期望值),var6:update(更新值)
*/
while (!unsafe.compareAndSwapLong(this, offset, current, current + 1)) {
current=counter;
}
}
@Override
public long getCounter() {
return counter;
}
}
3.3 测试类
/**
* @Description: 每个线程对Counter进行累加MAX_SUM次,MAX_THREAD个线程同时累加
* @Auther: zhurongsheng
* @Date: 2020/4/2 11:15
*/
public class UnsafeTest {
private static final int MAX_THREAD = 1000;
private static final int MAX_SUM = 10000;
public static void main(String[] args) throws Exception {
ExecutorService service = Executors.newFixedThreadPool(MAX_THREAD);
Counter counter = new CasCounter();
for (int i = 0; i < 1000; i++) {
service.submit(new CounterRunnable(counter, MAX_SUM));
}
//关闭不接受新任务
service.shutdown();
//阻塞,直到所有任务执行完毕 或 1小时后中断
service.awaitTermination(1, TimeUnit.HOURS);
System.out.println("Counter result:" + counter.getCounter());
}
}
4 unsafe创建对象绕过对象的构造
4.1 pojo
class Simple {
public Simple() {
System.out.println("Simple invoke NoArgsConstructor");
}
public void sayHello(){
System.out.println("hello world");
}
}
4.2 测试类
/**
* @Description: 通过Unsafe创建对象可以绕过对象的构造
* @Auther: zhurongsheng
* @Date: 2020/4/2 13:45
*/
public class UnsafeTest {
public static void main(String[] args) throws Exception {
//通过new 直接新建Simple
System.out.println("创建:");
new Simple();
//通过反射创建Simple
System.out.println("反射:");
Simple.class.newInstance();
//通过unsafe
System.out.println("【unsafe】:");
Unsafe unsafe = UnsafeUtils.getUnsafe();
Simple instance = (Simple) unsafe.allocateInstance(Simple.class);
instance.sayHello();
}
}
5 unsafe直接修改私有变量
5.1 pojo
class Simple {
private boolean access = false;
private boolean allow() {
return access == true;
}
public void work() {
if (allow()) {
System.out.println("工作使我快乐");
return;
}
System.out.println("我不要工作,来世我要当一个被子,要么躺床上,要么晒太阳。");
}
}
5.2 测试类
public class UnsafeTest {
public static void main(String[] args) throws Exception {
//1 直接new
System.out.println("直接创建对象:");
Simple simple1 = new Simple();
simple1.work();
System.out.println("###########################");
//2 反射
System.out.println("通过反射直接修改私有变量:");
Simple simple2 = Simple.class.newInstance();
Field access = simple2.getClass().getDeclaredField("access");
access.setAccessible(true);
access.set(simple2,true);
simple2.work();
System.out.println("###########################");
//3 unsafe
System.out.println("通过unsafe修改私有变量:");
Unsafe unsafe = UnsafeUtils.getUnsafe();
Simple simple3 = Simple.class.newInstance();
Field access1 = simple3.getClass().getDeclaredField("access");
//对象,偏移量,设置值
unsafe.putBoolean(simple3,unsafe.objectFieldOffset(access1),true);
simple3.work();
}
}