锁Lock核心原理

import org.apache.log4j.Logger;
import sun.misc.Unsafe;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by jz
 * 2020/11/9.
 */
public class UnsafeAccess {

    private static final String ANDROID = "THE_ONE";

    private static final String OPEN_JDK = "theUnsafe";

    private static Unsafe UNSAFE;

    static {
        Field field = null;
        try {
            field = Unsafe.class.getDeclaredField(OPEN_JDK);
        } catch (NoSuchFieldException e) {
            try {
                field = Unsafe.class.getDeclaredField(ANDROID);
            } catch (NoSuchFieldException e1) {
                try {
                    Constructor<Unsafe> constructor = Unsafe.class.getDeclaredConstructor();
                    constructor.setAccessible(true);
                    UNSAFE = constructor.newInstance();
                } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e2) {
                    throw new Error(e2);
                }
            }
        }
        if (field != null){
            field.setAccessible(true);
            try {
                UNSAFE = (Unsafe)field.get(null);
            } catch (IllegalAccessException e) {
                throw new Error(e);
            }
        }
    }

    private UnsafeAccess(){

    }

    public static Unsafe get(){
        return UNSAFE;
    }
}

class YYLock{

    private static Logger logger = Logger.getLogger(UnsafeAccess.class.getClass());

    private volatile int state = 0;

    private static long stateoffset;

    private static Unsafe unsafe;

    static {
        try {
            unsafe = UnsafeAccess.get();
            stateoffset = unsafe.objectFieldOffset(YYLock.class.getDeclaredField("state"));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateoffset, expect, update);
    }

    private Thread holdThread;

    public void setHoldThread(Thread thread){
        this.holdThread = thread;
    }

    private ConcurrentLinkedQueue<Thread> threads = new ConcurrentLinkedQueue<>();

    public void lock(){
        for (;;){
            logger.warn("------------------------------------------" + Thread.currentThread().getId() + "开始自旋!");
            if (compareAndSetState(0, 1)){
                logger.warn("------------------------------------------" + Thread.currentThread().getId() + "获取到了锁!");
                this.setHoldThread(Thread.currentThread());
                return;
            } else {
                logger.warn("------------------------------------------" + Thread.currentThread().getId() + "没有获取到锁!");
                threads.add(Thread.currentThread());
                LockSupport.park();
            }
        }

    }


    public void unlock(){
        if (Thread.currentThread() == holdThread && compareAndSetState(1, 0)){
            logger.warn("------------------------------------------" + Thread.currentThread().getId() + "释放了锁!");
            LockSupport.unpark(this.threads.poll());
        }
    }
}


class LockThread implements Runnable{

    private static Logger logger = Logger.getLogger(UnsafeAccess.class.getClass());

    private CyclicBarrier cyclicBarrier;
    private YYLockTest yyLockTest;
    public LockThread(CyclicBarrier cyclicBarrier, YYLockTest yyLockTest){
        this.cyclicBarrier = cyclicBarrier;
        this.yyLockTest= yyLockTest;
    }

    @Override
    public void run() {
        logger.warn("------------------------------------------" + Thread.currentThread().getId() + "准备就绪!");
        try {
            cyclicBarrier.await();
            yyLockTest.plus();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

class YYLockTest{

    private static Logger logger = Logger.getLogger(UnsafeAccess.class.getClass());

    YYLock yyLock = new YYLock();
//
//    ReentrantLock yyLock = new ReentrantLock();
    int a = 5;

    public void plus(){
        yyLock.lock();
        if (a > 0){
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            a--;
            logger.warn("------------------------------------------库存剩余:" + a);
        } else {
            logger.warn("------------------------------------------库存:" + a);
        }
        yyLock.unlock();
    }

    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(10);
        YYLockTest yyLockTest = new YYLockTest();
        LockThread lockThread = new LockThread(cyclicBarrier, yyLockTest);
        for (int i = 0; i < 10; i++){
            Thread thread = new Thread(lockThread);
            thread.start();
        }
    }
}

一.java中提供了常用的锁实现有以下两种

SynchronizedReentrantLock, 这两种锁区别是第一是以java关键字形式,基于monitor实现这样,我无法控制加锁与

第二是java-api级别这个锁开发者可以通lock()和unlock()自由控制。

这两种锁的性能在jdk1.6以后几乎有什太大的差。另一点是ReentrantLock他有公平和非公平之分。所公平就是所有线程想,必等待,而非公平就是如果此正好有线还没有加入等待列,则让插队,直接取到

二.ReentrantLock的实现原理(以公平锁举例)

1.猜想

    如何才能实现个锁

    1.所有线争抢执行一原子操作,行成功则获取到行失败则获取不到。

    里可以使用Unsafe类实现原子操作(CAS)

    2.一共享所有线程可以看到他的(volatile state)行CAS操作。

    3.如果取不到,其他线程如何理?

    --1)放弃,直接返回失

    --2)排等待,等待是一直让线程不停的去行原子操作,看是否成功?其挂起,等待取到线行成功后,通知他去行原子操作,取到

知道让线程一直不停的行命令是非常消耗CPU源的,所以应该采用第二方式。java提供了一个线程挂起和醒的工具LockSupport。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值