什么是锁?

简介: 什么是锁?

什么是锁?


说到锁,门闩,密码锁,指纹锁,虹膜识别锁等,在计算机世界中,单机线程没有锁的概念,当有了资源竞争,才有锁的贵爱安出现。表示自己短暂的持有。

计算机锁从最开始的悲观锁,然后发展到后来的乐观锁,偏向锁,分段锁等。

锁有两种特性:互斥性和不可见性。


JUC 中的锁


并发包的类族,Lock 是 JUC 包的顶层接口。实现逻辑并未用到 synchronized ,而是利用 volatile 的可见性。


640.png



Lock 的继承类图,ReentrantLock 对于 Lock 接口的实现主要依赖了 Sync, 而 Sync 继承了 AbstractQueuedSynchronizer(AQS), AQS 是实现同步的基础工具。


在 AQS 中定义了,定义了一个 volatile int state 变量作为共享资源,如果线程获取资源失败,则进入 同步的 FIFO  队列;如果成功获取资源就执行临界区代码。


protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

AQS 的子类可以定义不同性质的方法。


  • 比如可重入锁 ReentrantLock ,定义 State 为0 时,可以获取资源并设置1,如果已经获得资源,state 不断+1 ,释放资源 state-1 直到为0;
  • CountDown 初始化定义资源总量 state=count ,CountDown() 不断将 state-1 ,所以 CountDownLatch 是一次性的,用完之后只能重建一个,如果要循环使用,推进使用 CyclicBarrier 。
  • Semaphore 与 CountDownLatch 不同,定义了资源总量 state=permits. 当state >0 就可以获得锁,并将 state-1.当 state=0时只能等待其他线程释放锁。当释放锁时  state+1。当 Semaphore 的permits定义为1时,为互斥锁。permits>1 为共享锁。


CyclicBarrier 例子


每次 await 都会  count-1


int index = --count;

测试代码:


public class CyclicBarrierSample {
    /**
     * @param args
     */
    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(5, new Runnable() {
            @Override
            public void run() {
                System.out.println("Action.... go again!");
            }
        });
        for (int i = 0; i < 5; i++) {
            Thread t = new Thread(new CyclicWorker(barrier));
            t.start();
        }
    }
}
class CyclicWorker implements Runnable {
    private CyclicBarrier barrier;
    public CyclicWorker(CyclicBarrier barrier) {
        this.barrier = barrier;
    }
    /**
     * @see java.lang.Runnable#run()
     */
    @Override
    public void run() {
        try {
            for (int i = 0; i < 3; i++) {
                System.out.println("Executed!");
                barrier.await();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

CountDownLatch 代码


public class LatchSample {
    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(6);
        for(int i = 0; i < 5 ; i++){
            Thread t = new Thread(new FirstBatchWorker(latch));
            t.start();
        }
        for(int i = 0 ; i < 5;i++){
            Thread t = new Thread(new SecondBatchWorker(latch));
            t.start();
        }
        while(latch.getCount() != 1){
            Thread.sleep(100L);
        }
        System.out.println(" wait gor first batch finish");
        latch.countDown();
    }
}
class FirstBatchWorker implements Runnable {
    private CountDownLatch latch;
    public FirstBatchWorker(CountDownLatch latch) {
        this.latch = latch;
    }
    /**
     * @see java.lang.Runnable#run()
     */
    @Override
    public void run() {
        System.out.println("First batch executed!");
        latch.countDown();
    }
}
class SecondBatchWorker implements Runnable {
    private CountDownLatch latch;
    public SecondBatchWorker(CountDownLatch latch) {
            this.latch = latch;
    }
    @Override
    public void run() {
        try {
            latch.await();
            System.out.println("Second batch Executed!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


相关文章
|
人工智能 弹性计算 边缘计算
2020年国内十大云计算商排名榜
云计算在中国经过数年发展后,技术和市场都越发成熟。随着性能和稳定的提高,成本的降低,个人和企业用户都开始逐步接受云服务,但无论在全球范围还是中国范围内,云计算市场还只是起步阶段。 中国云市场来看,表面看似巨头已经瓜分天下,但实际上,出色的新秀在不断涌现,利用自己的特色优势在细分市场中分一杯羹。笔者根据企业实力,产品性能、性价比、服务评价等方面选出了市场认可度高的中国十大公有云计算服务商云计算服务商。
|
安全 应用服务中间件 文件存储
Kerberos网络身份认证协议介绍及SMB文件系统对其的支持
本文简单介绍了Kerberos网络认证协议,以及SMB文件系统对Kerberos认证的支持。
7666 1
Kerberos网络身份认证协议介绍及SMB文件系统对其的支持
|
运维 Kubernetes Docker
利用Docker和Kubernetes构建微服务架构
利用Docker和Kubernetes构建微服务架构
|
11月前
|
人工智能 移动开发 前端开发
温暖接力:“追星星的AI”再出发,志愿者招募令!
孤独症儿童绘本创作工具二期迭代开发,缺人!
335 21
温暖接力:“追星星的AI”再出发,志愿者招募令!
|
算法 安全 网络安全
阿里云SSL证书双11精选,WoSign SSL国产证书优惠
2024阿里云11.11金秋云创季活动火热进行中,活动月期间(2024年11月01日至11月30日)通过折扣、叠加优惠券等多种方式,阿里云WoSign SSL证书实现优惠价格新低,DV SSL证书220元/年起,助力中小企业轻松实现HTTPS加密,保障数据传输安全。
812 3
阿里云SSL证书双11精选,WoSign SSL国产证书优惠
|
11月前
|
缓存 监控 前端开发
探索前端性能优化:关键策略与代码实例
本文深入探讨前端性能优化的关键策略,结合实际代码示例,帮助开发者提升网页加载速度和用户体验,涵盖资源压缩、懒加载、缓存机制等技术。
|
11月前
|
SQL XML Java
mybatis实现动态sql
MyBatis的动态SQL功能为开发人员提供了强大的工具来应对复杂的查询需求。通过使用 `<if>`、`<choose>`、`<foreach>`等标签,可以根据不同的条件动态生成SQL语句,从而提高代码的灵活性和可维护性。本文详细介绍了动态SQL的基本用法和实际应用示例,希望对您在实际项目中使用MyBatis有所帮助。
602 11
|
存储 缓存 算法
OS—设备独立性软件
OS—设备独立性软件
548 0
|
Java Shell API
阿里短信服务API接入指南及示例
阿里短信服务,用淘宝账号打通三大运营商通信能力,以开放API方式向开发者提供短信服务。阿里短信服务具备3秒可达、99%到达率和超低资费的优势,并完美支撑了双11“2亿用户,6亿短信,8万并发”的挑战。本文将介绍阿里短信服务API如何接入,并提供了多种编程语言的调用示例。
114260 0
|
存储 缓存 网络协议
[计算机网络(第八版)]第一章 概述(章节测试 + 章节作业 + 答案解析)
[计算机网络(第八版)]第一章 概述(章节测试 + 章节作业 + 答案解析)