CAS和Synchronized的区别

1.什么是cas?
cas是乐观锁的一种实现方式,是一种轻量级锁,在java1.5的时候开始引入
2.cas的实现原理?
cas有3个操作数,内存值V,旧的预期值A,要更新的新值C,当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么也不做.当多个线程同时尝试使用CAS更新一个变量时,任何时候只有一个线程可以更新成功,若失败线程会重新进入循环再次进行尝试.
cas的核心实现是unsafe,unsafe类是使java有了像c一样的操作内存空间的能力,一旦能够直接操作内存就意味着不受jvm管理,也就无法被GC,需要我们手动GC,所以很容易造成内存泄漏.具体详情不在这里展开.
3.cas的ABA问题和解决办法?*
ABA问题就是俩个线程1和2,线程1从内存X中取出A,线程2也从内存中取出A,并且将A变成了B,然后线程2又将B变成了A,这时候线程1执行cas操作成功,虽然线程1执行成功了但是执行成功的A已经不是原来获取的A了,整个执行过程是有问题的,比如链表的头在进行了俩次变化后恢复为原来的值并不代表链表就没有发生变化.
解决办法:在对象中额外再增加一个字段,用来标识有没有发生过变化,比如version,每次变化进行加1或者用当前时间戳.
4.CAS的不足?
1.如果CAS操作不成功的话,会一直自旋直到成功,cpu消耗会很大.
2.不能保证多个操作的原子性.
3.cas存在ABA问题
3.Synchronized的实现原理**
Synchronized的主要作用有三个:
1.原子性:确保线程互斥的访问同步的代码
2.可见性: 保证共享变量的修改能够及时的可见,
3.有序性:有效解决重排的问题
synchronized的用法
1.当Synchronized用在实例方法上时,监视锁(monitor)便是对象实例
2.当用在静态方法上时,监视的便是对象的class,因为class存在永久代,因此静态方法锁相当于该类的一个全局锁
3.当作用在一个对象实例时monitor便是括号括起来的对象实例
锁的分类
1.自旋锁
当一个线程尝试获取某个锁时,如果该锁已经被其他线程占用,就一直循环检测锁是否被释放,而不是进入挂起或者睡眠状态
自旋锁适用于锁保护的临界区很小的情况,临界区很小的话,锁占用的时间就很短。自旋等待不能替代阻塞,虽然它可以避免线程切换带来的开销,但是它占用了CPU处理器的时间。如果持有锁的线程很快就释放了锁,那么自旋的效率就非常好,反之,自旋的线程就会白白消耗掉处理的资源,它不会做任何有意义的工作,典型的占着茅坑不拉屎,这样反而会带来性能上的浪费。所以说,自旋等待的时间(自旋的次数)必须要有一个限度,如果自旋超过了定义的时间仍然没有获取到锁,则应该被挂起。

自旋锁在JDK 1.4.2中引入,默认关闭,但是可以使用-XX:+UseSpinning开开启,在JDK1.6中默认开启。同时自旋的默认次数为10次,可以通过参数-XX:PreBlockSpin来调整。

如果通过参数-XX:PreBlockSpin来调整自旋锁的自旋次数,会带来诸多不便。假如将参数调整为10,但是系统很多线程都是等你刚刚退出的时候就释放了锁(假如多自旋一两次就可以获取锁),是不是很尴尬。于是JDK1.6引入自适应的自旋锁,让虚拟机会变得越来越聪明
2.适应性自旋锁
JDK 1.6引入了更加聪明的自旋锁,即自适应自旋锁。所谓自适应就意味着自旋的次数不再是固定的,它是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。那它如何进行适应性自旋呢?

线程如果自旋成功了,那么下次自旋的次数会更加多,因为虚拟机认为既然上次成功了,那么此次自旋也很有可能会再次成功,那么它就会允许自旋等待持续的次数更多。反之,如果对于某个锁,很少有自旋能够成功,那么在以后要或者这个锁的时候自旋的次数会减少甚至省略掉自旋过程,以免浪费处理器资源。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值