锁是用来在多线程并发阶段保障数据同步的重要手段,防止出现脏数据,加锁代码在某个时间点只能由一个线程运行,其他线程等待。
普遍熟知的锁是synchronized关键字和Lock类。
一、synchronized关键字
这个在同步中是最常用的,分成对象锁和类锁,可以对方法和代码块进行加锁。
1、对象锁,锁住的是对象,用于
synchronized(this){}
synchronized(Object){}
2、类锁,锁住的是该类的所有实例
synchronized(Object.class){}
synchronized锁是在字节码级别上的锁,可以用javap(java自带的反编译工具)查看
例如查看这一段代码的字节码指令
javap执行结果如下:
可以看到是由monitorenter和monitorexit指令来实现加锁的,出现两次的monitorexit是为了确保解锁完成。
二、Lock
Lock是接口,有以下几个方法
1、获取锁
lock()
2、获取锁,除非线程中断
lockInterruptibly()
3、尝试获取锁,在锁可用获取锁
tryLock()
4、解锁
unlock()
5、返回该Lock的condition
newCondition()
Lock是需要配合Condition使用的,其有await和signal方法,类似于Object的wait和notify方法。
主要看一下Lock的实现类ReentrantLock。
(1)ReentrantLock默认是非公平锁(获取锁的顺序不是按照申请顺序来)
public ReentrantLock() { sync = new NonfairSync();}
也可以用参数指定是公平锁OR非公平锁
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync();}
FairSync和NonFairSync是继承Sync的,而Sync是继承自AbstractQueuedSynchronizerÿ