首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >手写锁lock

手写锁lock

作者头像
分享干货的你
发布2021-04-06 16:59:44
发布2021-04-06 16:59:44
63300
代码可运行
举报
文章被收录于专栏:分享干货的你分享干货的你
运行总次数:0
代码可运行

最近在做公司业务的时候, 使用到了隐式的锁,synchronize , 其实就是jvm 多了一个montior 的监视器,

我们先写一个代码

运行一下,生成class文件,再用 Javap -v 打印所有的字节码信息。

monitorenter 开始监视,monitorexit 监视退出, 为啥有两个啊。

一个正常退出,一个不正常退出。这是synchronize 隐式锁的原理,现在我们来说说一下lock , 底层就是cas 原理,在加上一个队列。

我们要自己写一个锁,要实现lock, unlock 的方法, 线程之间要显示的通讯,这里我们用LockSupport, 进行阻塞,唤醒等

底层是unsafe 直接操作字节码的,本地方法的。先说一下设计思路啊

AtomicReference 类,来作为对象的原子引用,在用linkedBlockingQueue 队列存放阻塞的线程, 加锁的实现,先 获取当前线程,进行cas 看一下是否成功,进行死循环, 不成功,先阻塞,把其他的线程加入队列

等到不阻塞的时候,在把队列的线程给释放了。防止内存泄漏。

解锁就是遍历队列,唤醒所有阻塞的线程, 这里唤醒所有的默认是非公平的,不一定排在最前的就能获得锁

现在我们来开始写代码,先实现lock

这里没有指定队列的大小,因为add 的时候默认的 就是integer.max

我们写一个代码测试一下,先测试不加锁和加锁的代码

代码语言:javascript
代码运行次数:0
运行
复制
  public static int count = 0;

    public static void increase() {
        count++;
    }

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[20];
        for (int i = 0; i < 20; i++) {
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 1000; i++) {
                        increase();
                    }
                }
            });
            threads[i].start();
        }
        while (Thread.activeCount() > 1) {
            Thread.yield();
        }
        System.out.println(count);
    }

运行结果 ,正确结果应该是20000,

这说明并发,没有保障原子性。加上我们自己写锁

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-09-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 分享干货的你 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档