Synchronized与Lock的区别
- Synchronized 内置的Java关键字,Lock是一个Java类
- Synchronized 无法判断获取锁的状态,Lock可以判断
- Synchronized 会自动释放锁,lock必须要手动加锁和手动释放锁!可能会遇到 死锁
- Synchronized 线程1(获得锁、阻塞)、线程2(等待、继续等待);lock就不一定会一直等待下去,lock会有一个trylock去尝试获取锁,不会造成长久的等待
- Synchronized 是可重入锁,不可以中断的,非公平的;Lock,可重入锁,可以判断锁,可以自己设置公平锁和非公平锁
- Synchronized 适合锁少量的代码同步问题,Lock适合锁大量的同步代码;
synchronize和lock的用法区别
synchronize:在需要同步的对象中加入此控制,synchronize可以加在方法上(同步方法),也可以加在特定代码块中(同步代码块),括号中表示需要锁的对象。
lock:需要显示指定起始位置和终止位置。一般使用ReentranLock类做为锁,多个线程中必须要使用一个ReentranLock类做为对象才能保证锁的生效。且在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。
synchronized和lock性能区别
synchronized是托管给JVM执行的,而lock是java写的控制锁的代码。在Java1.5中,synchronized是性能很低效的。因为这是一个重量级操作。需要调用操作接口,导致有可能加锁消耗的系统时间比加锁以外的操作还多。相比之下使用java提供的lock对象,性能更高一些。但是到了JDK1.6,发生了变化。synchronize在语义上很清晰,可以进行很多优化,有适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等。导致在Java1.6上synchronize的性能并不比Lock差。官方也表示,他们也更支持synchronize,在未来的版本中还有优化余地。
说到这里,还是想提一下这两种机制的具体区别。据我所知,synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。
而lock用的是乐观锁方式,所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就是CAS操作(Compare and Swap)。我们可以进一步研究ReentrantLock的源代码,会发现其中比较重要的获得锁的一个方法是compareAndSetState。这里其实就是调用的CPU提供的特殊指令。
现代的CPU提供了指令,可以自动更新共享数据,而且能够检测其他线程的干扰,而 compareAndSet() 就用这些代替了锁定。这个算法称作非阻塞算法,意思是一个线程的失败或者挂起不应该影响其他线程的失败或挂起的算法。
synchronized和lock用途区别
synchronized原语和ReentrantLock在一般情况下没有什么区别,但是在非常复杂的同步应用中,请考虑使用ReentrantLock,特别是遇到下面2种需求的时候。
-
某个线程在等待一个锁的控制权的这段时间需要中断。
-
需要分开处理一些wait(等待)-notify(唤醒),ReentrantLock里面的Condition应用(Condition定义了等待await/通知signal、signalAll两种类型的方法),能够控制notify哪个线程。
-
具有公平锁功能,每个到来的线程都将排队等候。
公平锁与非公平锁
- 公平锁: 十分公平,必须先来后到;
- 非公平锁: 十分不公平,可以插队;