概述
Java技术中的锁机制是高并发采用多线程编程中的非常重要一环,用于解决资源竞争问题。
Java 中的并发锁大致分为隐式锁和显式锁两种。隐式锁就是我们最常使用的 synchronized 关键字,显式锁主要包含两个接口:Lock 和 ReadWriteLock,主要实现类分别为 ReentrantLock 和 ReentrantReadWriteLock,这两个类都是基于 AQS(AbstractQueuedSynchronizer) 实现的。
CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术。简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替换当前变量的值。
很多地方把CAS也归于JAVA并发编程的锁机制。
隐式锁和显式锁的区别
层面不同
Synchronized:Java中的关键字,是由JVM来维护的,是JVM层面的锁;
Lock:是JDK5以后才出现的具体的类,使用lock是调用对应的API,是API层面的锁;
synchronized是底层是通过monitorenter进行加锁(底层是通过monitor对象来完成的,其中的wait/notify等方法也是依赖于monitor对象的。只有在同步块或者是同步方法中才可以调用wait/notify等方法的。因为只有在同步块或者是同步方法中,JVM才会调用monitory对象的);通过monitorexit来退出锁的。
而lock是通过调用对应的API方法来获取锁和释放锁的。
使用方法不同
A.锁的释放
- Synchronized直接作用于方法上,并且不需要开发者手动去释放锁,如果发生异常,JVM会通知线程释放锁
- Lock需要先创建对象,并且手动释放锁,在使用规范中必须在finally中执行,且容易造成死锁。
B.锁的获取
- Synchronized:线程1获得锁,线程2会一直等待
- Lock:可以通过trylock来知道有没有获取锁,可以设置阻塞等待时间;可以通过readwritelock实现读写分离
C.中断响应
- Lock支持用interrupt来中断等待
- Synchronized不能响应中断;
D.调度机制
- Synchronized:使用Object对象本身的wait 、notify、notifyAll调度机制
- Lock可以使用Condition进行线程之间的调度
Synchronized的几种用法
- 同步普通方法(锁实例对象)
public synchronized void testOne(){
System.out.println("同步普通方法(锁实例对象)");
}
- 同步静态方法(锁类本身)
public synchronized static void testTwo(){
System.out.println("同步静态方法(锁类本身)");
}
- 同步类(锁类本身)
public void testThree(){
synchronized(SynchronizedService.class){
System.out.println("同步类(锁类本身)");
}
synchronized(this.getClass()){
System.out.println("同步类(锁类本身)");
}
}
- 同步this实例(锁实例对象)
public void testFour(){
synchronized(this){
System.out.println("同步this实例(锁实例对象)");
}
}
- 同步对象实例(锁实例对象)
private Object object = new Object();
public void testFive(){
synchronized(object){
System.out.println("同步对象实例(锁实例对象)");
}
}
锁类本身,该类所有的对象同一把锁。 实例对象仅限制当前线程,多线程不起作用;testFive中如果object是静态方法,不管多少个实例,只有一个线程可以获取到锁,没有static修饰就是当前实例。
E.锁机制的区别
Synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。
而Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就是CAS操作(Compare and Swap)。我们可以进一步研究ReentrantLock的源代码,会发现其中比较重要的获得锁的一个方法是compareAndSetState。这里其实就是调用的CPU提供的特殊指令。
Synchronized有个性能优化的小课题
后续再说哈。。。。。。