莫大人

锁分析 Lock

锁分析
Lock
	NonReentrantLock
	ReadLock	共享锁
	ReentrantLock 重入锁	排他锁
		sync.lock	返回值为void,表示如无异常发生都认为锁获取成功
			FairSync.lock	公平锁
				FairSync.tryAcquire
				获取线程
				获取线程重入次数
				重入次数为0
					是 也就是第一次获取锁
						在队列头部(队列为空或者当前线程在队列头部)
							获取锁 设置锁状态 重入次数
							设置锁的独占线程
							获取锁成功
					否
						当前线程是否是锁的独占线程
							是
								重入次数+1 成功获取锁
							否
								获取锁失败
			NonfairSync.lock	非公平锁
				NonfairSync.lock
				按照假设当前线程是第一次获取锁来申请锁
					成功
						设置当前线程为锁的独占线程
					失败
						按照重入的方式获取锁
	WriteLock	排他锁

	

CAS 存在ABA的问题
ReentrantLock 重入锁默认构造是非公平锁实现,当申请锁的线程刚好碰到正在执行的线程释放了锁,那么他就有机会直接获取到锁,而不用排队。

重入锁的公平锁实现原理:
如果当前线程第一次获取锁,如果当前线程在抽象队列同步执行器的队首位置,利用CAS原理修改线程重入次数为1,成功则修改锁的独占线程为当前线程。
如果当前线程不是第一次获取锁,那么判断当前锁的独占线程与当前获取锁的线程是否一致,如果一致那么获取锁成功。

重入锁的非公平锁实现原理:
尝试按照第一次获取锁的方式直接获取锁,成功则获取锁成功
失败则重入的方式获取锁(判断当前线程与锁的独占锁是否一致)

 
Lock本地锁应用场景 
根据锁创建的位置可以分为,对象锁,全局锁
1、对象锁,对象持有锁,在并发访问对象资源时可以用该锁控制。
public class ObjectLock {

    private Lock objectLock = new ReentrantLock();
    
    void objectLock(Ticket ticket) {
        objectLock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+":"+ticket.getNum());
            ticket.setNum(ticket.getNum()+1);
            Thread.sleep(1000);
        } catch (Exception e) {
            Console.error(e);
        } finally {
            objectLock.unlock();
        }
    }
    
}

 

2、全局锁,创建一个静态常量的锁,在系统全局都可以使用该锁。
public interface LockConstant {

    Lock lock = new ReentrantLock();
    
}
void lockConstant(Ticket ticket) {
        Lock lock = LockConstant.lock;
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+":"+ticket.getNum());
            ticket.setNum(ticket.getNum()+1);
            Thread.sleep(100);
        } catch (Exception e) {
            Console.error(e);
        } finally {
            lock.unlock();
        }
    }

 



posted on 2019-06-12 17:54  莫大人  阅读(175)  评论(0编辑  收藏  举报

导航