1. package com.enjoy.util;
    2. import sun.misc.Unsafe;
    3. import java.lang.reflect.Field;
    4. import java.util.concurrent.atomic.AtomicBoolean;
    5. public class CASLock {
    6. private volatile int status = 0;//标识---是否有线程在同步块-----是否有线程上锁成功
    7. //获取Unsafe对象,只能这么获取,Unsafe这个类比较难有兴趣同学可以自己研究研究
    8. //窃以为Unsafe是java里面最牛逼的一个对象,没有之一
    9. private static final Unsafe unsafe = getUnsafe();
    10. //定义一个变量来记录 volatile int status的地址
    11. //因为CAS需要的是一个地址,于是就定义这个变量来标识status在内存中的地址
    12. private static long valueOffset = 0;
    13. /**
    14. * 初始化的获取status在内置的偏移量
    15. * 说白了就是status在内存中的地址
    16. * 方便后面对他进行CAS操作
    17. */
    18. static {
    19. try {
    20. valueOffset = unsafe.objectFieldOffset
    21. (CASLock.class.getDeclaredField("status"));
    22. } catch (Exception ex) {
    23. throw new Error(ex);
    24. }
    25. }
    26. /**
    27. * 加锁方法
    28. */
    29. public void lock() {
    30. /**
    31. * 判断status是否=0;如果等于0则改变成为1
    32. * 而判断赋值这两个操作可以通过一个叫做CAS的技术来完成
    33. * 通过cas去改变status的值,如果是0就改成1
    34. * 思考一下为什么要用CAS
    35. * 关于CAS如果你不了解可以先放放,后面我们讲
    36. * 目前就认为CAS用来赋值的和 = 的效果一样
    37. */
    38. while (!compareAndSet(0, 1)) {
    39. //加锁失败会进入到这里空转
    40. }
    41. // 如果加锁成功则直接正常返回
    42. }
    43. //为什么unlock不需要CAS呢?可以自己考虑一下,如果不懂可以讨论
    44. public void unlock() {
    45. status = 0;
    46. }
    47. boolean compareAndSet(int except, int newValue) {
    48. //如果 valueOffset或者 status这个变量 = except 那么改成 newValue
    49. return unsafe.compareAndSwapInt(this, valueOffset, except, newValue);
    50. }
    51. /**
    52. * 获取Unsafe对象
    53. *
    54. * @return
    55. */
    56. public static Unsafe getUnsafe() {
    57. try {
    58. Field field = Unsafe.class.getDeclaredField("theUnsafe");
    59. field.setAccessible(true);
    60. return (Unsafe) field.get(null);
    61. } catch (Exception e) {
    62. }
    63. return null;
    64. }
    65. }