前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >volatile,synchronized,ReentrantLock

volatile,synchronized,ReentrantLock

作者头像
提莫队长
发布2019-02-21 15:11:19
5570
发布2019-02-21 15:11:19
举报
文章被收录于专栏:刘晓杰刘晓杰刘晓杰

synchronized

实现机制:反编译以后monitor 优化:自旋锁,适应自旋锁,轻量级锁等 所谓自旋锁,就是让该线程等待一段时间,不会被立即挂起,看持有锁的线程是否会很快释放锁。怎么等待呢?执行一段无意义的循环即可(自旋)。 虽然可以避免线程切换带来的开销,但是占用处理器时间

volatile

原子性:一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。(volatile是无法保证复合操作的原子性) 可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。(Java提供了volatile来保证可见性) 有序性:程序执行的顺序按照代码的先后顺序执行。(Java提供volatile来保证一定的有序性) 使用它必须满足如下两个条件:

对变量的写操作不依赖当前值;
该变量没有包含在具有其他变量的不变式中。

volatile经常用于两个场景:状态标记、double check

ReentrantLock

AQS,AbstractQueuedSynchronizer,即队列同步器。 AQS使用一个int类型的成员变量state来表示同步状态,当state>0时表示已经获取了锁,当state = 0时表示释放了锁。它提供了三个方法(getState()、setState(int newState)、compareAndSetState(int expect,int update))来对同步状态state进行操作,当然AQS可以确保对state的操作是安全的。 AQS通过内置的FIFO同步队列来完成资源获取线程的排队工作,如果当前线程获取同步状态失败(锁)时,AQS则会将当前线程以及等待状态等信息构造成一个节点(Node)并将其加入同步队列,同时会阻塞当前线程,当同步状态释放时,则会把节点中的线程唤醒,使其再次尝试获取同步状态。 该队列就是CLH同步队列。CLH同步队列是一个FIFO双向队列,AQS依赖它来完成同步状态的管理

    private Node addWaiter(Node mode) {
        Node node = new Node(mode);

        for (;;) {
            Node oldTail = tail;
            if (oldTail != null) {
                //尾节点不为null就添加到尾节点的next(CAS)
                U.putObject(node, Node.PREV, oldTail);
                if (compareAndSetTail(oldTail, node)) {
                    oldTail.next = node;
                    return node;
                }
            } else {
                //尾节是null就初始化整个队列
                initializeSyncQueue();
            }
        }
    }

前面提到ReentrantLock提供了比synchronized更加灵活和强大的锁机制,那么它的灵活和强大之处在哪里呢?他们之间又有什么相异之处呢? 首先他们肯定具有相同的功能和内存语义。 与synchronized相比,ReentrantLock提供了更多,更加全面的功能,具备更强的扩展性。例如:时间锁等候,可中断锁等候,锁投票。 ReentrantLock还提供了条件Condition,对线程的等待、唤醒操作更加详细和灵活,所以在多个条件变量和高度竞争锁的地方,ReentrantLock更加适合(以后会阐述Condition)。 ReentrantLock提供了可轮询的锁请求。它会尝试着去获取锁,如果成功则继续,否则可以等到下次运行时处理,而synchronized则一旦进入锁请求要么成功要么阻塞,所以相比synchronized而言,ReentrantLock会不容易产生死锁些。 ReentrantLock支持更加灵活的同步代码块,但是使用synchronized时,只能在同一个synchronized块结构中获取和释放。注:ReentrantLock的锁释放一定要在finally中处理,否则可能会产生严重的后果。 ReentrantLock支持中断处理,且性能较synchronized会好些。

条件Condition说明(http://blog.csdn.net/chenssy/article/details/69279356)一个有头结点和尾节点的单向队列

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年06月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

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