您的位置:首页 > 编程语言 > Java开发

Java多线程中Synchronized和Lock的区别

2017-06-25 12:00 495 查看
之前已经介绍过了Synchronized锁的实现原理,简单概括就是在JVM层运用了object的monitor来实现同步。而Lock是Java大神 Doug Lea 开发的util.concurrent中的一个锁工具,它实现了Synchronized的所有功能。下面从使用、性能这两个部分来具体分析两者的不同。

一.Synchronized和Lock的用法区别

Synchronized:在需要同步的对象中加入此关键字,可以加在方法上、代码块中,可以添加加锁的对象,不添加则默认是该类或该class对象。
Lock:需要显示的加在需要同步的开始和结束处。一般使用ReentrantLock类为锁。使用lock()方法加锁,unlock()方法解锁,unlock方法一般要放在finally块中保证一定执行。区别于Synchronized,在使用wait()和notify()方法中,Synchronized是无条件的阻塞和唤醒。而Lock可以使用内置的Condition类来区别唤醒不同的对象。

二.Synchronized和Lock的性能区别

Synchronized是JVM层面执行的指令,而Lock是Java写的控制线程的代码。在Java1.6之前,Synchronized一直被称为重量级锁,因为它需要调用操作系统的线程指令,导致有可能加锁消耗的资源比加锁以外的操作还多。相比之下,Lock的性能很可能更高一些,它不需要调用系统的阻塞操作,具体的实现我后面的文章会同大家一起分析。不过,在Java1.6之后,对Synchronized进行了各种优化,如自适应自旋(轻量级锁中等使用)、锁粗化(合并锁)、偏向锁(单线程使用)、锁消除等技术,致使Java1.6上,Synchronized的性能并不比Lock差。
此外,Synchronized采用了悲观锁的机制,顾名思义,它假设每次执行同步的时候,别的线程总会也去执行,所以每次都会上锁。线程获得的是独占锁,意味着其他线程只能依靠阻塞来等待占有线程来释放锁。而CPU阻塞和唤醒线程会引起上下文切换,大量线程竞争锁的时候,导致低效。
而Lock使用了乐观锁的方式,顾名思义,就是每次不加锁而是假设没有冲突而去完成操作。它是基于CAS操作的(Compare And Swap),通过竞争Lock内置队列同步器(AQS)中的状态位state,填充入自己的线程来获得锁。
现代CPU提供了指令,可以自动更新共享数据,而且能够检测其他线程的干扰,而compareAndSet()就用这些代替了锁定,这是一个自旋而非阻塞的算法,不会被挂起或者影响其他线程。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程