1、隐式锁 对称线程同步 synchronized
用法:1、在方法声明时使用;2、修饰代码块中使用
隐式规则
1、当两个并发线程访问同一个对象object中的synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行
2、当一个线程访问object的一个synchronized(this)同步代码块时,其他的线程可以访问该object中的非synchronized(this)同步代码块
3、synchronized(this)设置的对象锁中,当一个线程访问获取到锁,其他线程对object中相同对象锁的代码块都无法访问
性能和执行效率:
同步方法体<同步代码块 <synchronized(this)<同步代码块(byte锁)
如图1-2
关于效率高低的判断,其实记住一点,锁时一个对象,加锁和释放锁都需要资源,对象越小效率越高
2、显式锁Lock和ReentrantLock
Lock只是一个接口,它规定了锁的基础操作规范
如图2-1所示
1、Lock()方法,线程获取锁,如果锁不可用,则禁用当前线程,在获得锁之前,该线程一直处于休眠
2、unlock()方法,释放锁,一般情况下,每个获取的锁都要对应一个释放锁
其他的方法像是lockInterruptibly、tryLock、tryLock(long time, TimeUnit unit)这几个方法无非就是在获取锁的过程中判断了一些条件,这里需要注意的是,方法中的锁一定要是共有的,如果是独立的锁,那么起不到相应的作用
3、显示锁,读写锁ReadWriteLock和ReentrantReadWriteLock
ReadWriteLock是一个接口,只有两个方法,readLock()和writeLock(),此处注意,ReadWriteLock并不是Lock的子接口,但是ReadWriteLock中的读写锁都是依靠Lock来进行实现的
读写锁的机制:
1、读读不互斥:多线程读,并发不堵塞
2、读写互斥:有线程在写,那么所有的读线程就会堵塞,反过来,有读的线程在使用,写线程就会堵塞
3、写写互斥:写线程都是互斥的,两个线程去写,谁先拿到锁,就先写
图3-1中是同时使用读写锁的时候的业务场景,比较经典的缓存场景
图3-2和图3-3则是模拟高并发的情况下的读写锁单独使用的情况下,图3-2的是模拟高并发的单元测试代码,图3-3是读写锁的代码
读写锁和普通锁的区别,
1、相同点:其实都是一种显式锁,手动加锁和解锁,都比较适合高并发场景
2、不同点:ReentrantReadWriteLock是对ReentrantLock的一种扩展,ReentrantReadWriteLock适合更加复杂的业务场景,可以实现一个方法的读写分离