8锁:
1.⼀个对象⾥⾯如果有多个synchronized⽅法,某⼀个时刻内,只要⼀个线程去调⽤其中
的⼀个synchronized⽅法了,其他的线程都只能等待,换句话说,某⼀个时刻内,只能有唯⼀⼀个线程去访问这些synchronized⽅法,
锁的是当前对象this,被锁定后,其他的线程都不能进⼊到当前对象的其他的
synchronized⽅法
2.加个普通⽅法后发现和同步锁⽆关
3.换成两个对象后,不是同⼀把锁了,情况⽴刻变化
4.全局锁
synchronized实现同步的基础: java中的每⼀个对象都可以作为锁。
具体表现为以下3中形式。
对于普通同步⽅法,锁是当前实例对象,锁的是当前对象this,
对于同步⽅法块,锁的是synchronized括号⾥配置的对象。
对于静态同步⽅法,锁是当前类的class对象
5.
1.异常会自动释放锁
当⼀个线程试图访问同步代码块时,它⾸先必须得到锁,退出或抛出异常时必须释放锁。
2.普通对象锁里面的方法只能一个进入,其他的方法不能同时进入
也就是说如果⼀个实例对象的普通同步⽅法获取锁后,该实例对象的其他普通同步⽅法必
须等待获取锁的⽅法释放锁后才能获取锁,
3.多个实例访问枷锁方法,由于是不同的锁所以可以进行同时访问
可是别的实例对象的普通同步⽅法因为跟该实例对象的普通同步⽅法⽤的是不同的锁,
所以⽆需等待该实例对象已获取锁的普通同步⽅法释放锁就可以获取他们⾃⼰的锁。
4.静态方法和普通方法是不同的锁:
所有的静态同步⽅法⽤的也是同⼀把锁--类对象本身,
这两把锁(this/class)是两个不同的对象,所以静态同步⽅法与⾮静态同步⽅法之间是
不会有静态条件的。但是⼀旦⼀个静态同步⽅法获取锁后,其他的静态同步⽅法都必须等待该⽅法释放锁后才能获取锁,⽽不管是同⼀个实例对象的静态同步⽅法之间,还是不同的实例对象的静态同步⽅法之间,只要它们同⼀个类的实例对象
ReentrantLock:默认非公平锁
所谓公平锁,就是多个线程按照申请锁的顺序来获取锁,类似排队,先到先得。⽽⾮公平锁,则
是多个线程抢夺锁,会导致优先级反转或饥饿现象,比如个子小的人排队永远在最后
⾮公平锁的优点是吞吐量⽐公平锁更⼤
可重⼊锁/递归锁
可重⼊锁⼜叫递归锁,指的同⼀个线程在外层⽅法获得锁时,进⼊内层⽅法会⾃动获取锁。也就是说,线程可以进⼊任何⼀个它已经拥有锁的代码块。⽐如 func1 ⽅法⾥⾯有 func2 ⽅法,两个⽅法
都有同⼀把锁,得到了 func1 的锁,就⾃动得到了 func2 的锁。可重⼊锁可以避免死锁的问题
锁之间要配对,加了⼏把锁,最后就得解开⼏把锁
⾃旋锁
就是尝试获取锁的线程不会⽴即阻塞,⽽是采⽤循环的⽅式去尝试获取。⾃⼰在那⼉⼀直
循环获取,就像“⾃旋”⼀样。这样的好处是减少线程切换的上下⽂开销,缺点是会消耗CPU
读锁是共享的, 写锁是独占的。 juc.ReentrantLock 和 synchronized 都是独占锁,独占锁就是⼀个锁只能被⼀个线程所持有。有的时候,需要读写分离,那么就要引⼊读写锁
独占锁:指该锁⼀次只能被⼀个线程所持有。对ReentrantLock和Synchronized⽽⾔都是独占锁
共享锁:指该锁可被多个线程所持有
对ReenntrantReadWriteLock其读锁是共享锁,其写锁是独占锁。
读锁的共享锁可保证并发读是⾮常⾼效的,读写、写读、写写的过程是互斥的
CountDownLatch 内部维护了⼀个计数器,只有当计数器==0时,某些线程才会停⽌阻塞,开始执⾏
CyclicBarrier 是加,⽐如10个人到齐了才开饭
CountDownLatch 的问题是不能复⽤。⽐如 count=3 ,那么加到3,就不能继续操作了。
⽽ Semaphore 可以解决这个问题,⽐如6辆⻋3个停⻋位,对于 CountDownLatch 只能停3辆⻋,
前三辆车进来就阻塞,等有车离开又可以进来新的车