锁类型
1.可重入锁
2.公平锁
多个线程按照申请锁的顺序获得锁 线程会直接进入队列去排队 永远都是队列的第一位才能得到锁 排队不插队 优点
所有的线程都能得到资源,不会饿死在队列中
吞吐量会下降很多,队列里面除了第一个线程,其他的线程都会阻塞,cpu唤醒阻塞线程的开销会很大
源码
3.非公平锁
多个线程申请锁时,直接尝试获取锁,获取不到进入队列去排队 优点
减少CPU唤醒线程的开销,整体的吞吐效率会高点,减少CPU唤起线程的数量
导致队列中间的线程一直获取不到锁或者长时间获取不到锁,导致饿死
4.自旋锁
public class SafeIncrement {
private AtomicInteger atomicI = new AtomicInteger ( 0 ) ;
public void increament ( ) {
for ( ; ; ) {
int i = atomicI. get ( ) ;
boolean suc = atomicI. compareAndSet ( i, ++ i) ;
if ( suc) {
break ;
}
}
}
}
显式锁
1.Lock
Lock与synchronized比较 synchronized可重入证明
public class Re_synchronized {
public synchronized void method1 ( ) {
System . out. println ( "11111" ) ;
method2 ( ) ;
}
public synchronized void method2 ( ) {
System . out. println ( "22222" ) ;
}
public static void main ( String [ ] args) {
Re_synchronized re = new Re_synchronized ( ) ;
re. method1 ( ) ;
}
}
public class Re_reentrantLock implements Runnable {
Lock lock = new ReentrantLock ( ) ;
@Override
public void run ( ) {
set ( ) ;
}
public void set ( ) {
try {
lock. lock ( ) ;
System . out. println ( "set" ) ;
get ( ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
} finally {
lock. unlock ( ) ;
}
}
public void get ( ) {
try {
lock. lock ( ) ;
System . out. println ( "get" ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
} finally {
lock. unlock ( ) ;
}
}
public static void main ( String [ ] args) {
Re_reentrantLock re = new Re_reentrantLock ( ) ;
new Thread ( re) . start ( ) ;
}
}
1. void lock ( ) :相当synchronized ,获得锁
2. void unlock ( ) :释放锁,用于finally 中
3. lockInterruptibly ( ) :
4. boolean tryLock ( ) :锁可用立即返回true
5. boolean tryLock ( long time, TimeUnit unit)
6. newCondition ( ) :看下面
2.Condition
1. await ( ) :相当Object . wait ( )
2. singal ( ) :相当Object . notify ( ) ,随机唤醒
3. singalAll ( ) :相当Object . notifyAll ( )
class AppleBox {
int index = 0 ;
Apple [ ] apples = new Apple [ 5 ] ;
private final Lock lock = new ReentrantLock ( ) ;
private final Condition produceCondition = lock. newCondition ( ) ;
private final Condition consumeCondition = lock. newCondition ( ) ;
public void deposite ( Apple apple) throws InterruptedException {
lock. lock ( ) ;
try {
while ( index == apples. length) {
produceCondition. await ( ) ;
}
consumeCondition. signal ( ) ;
apples[ index] = apple;
index++ ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
} finally {
lock. unlock ( ) ;
}
}
public Apple withdraw ( ) {
lock. lock ( ) ;
try {
while ( index == 0 ) {
consumeCondition. await ( ) ;
}
produceCondition. signal ( ) ;
index-- ;
return apples[ index] ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
} finally {
lock. unlock ( ) ;
}
return null ;
}
}
3.ReentrantLock
4.ReentrantReadWriteLock
读多写少 情况使用读锁与写锁不能同时拥有 读锁在读操作间共享 写锁在读写操作间都独占(排他锁) 案例
public class ReentrantReadWriteLockTest {
private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock ( ) ;
private static ThreadPoolExecutor executor = new ThreadPoolExecutor ( 10 , 10 , 60L , TimeUnit . SECONDS, new LinkedBlockingQueue < Runnable > ( ) ) ;
private static CyclicBarrier cyclicBarrier = new CyclicBarrier ( 4 ) ;
private static int i = 100 ;
public static void read ( Thread thread) {
try {
cyclicBarrier. await ( ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
reentrantReadWriteLock. readLock ( ) . lock ( ) ;
try {
System . out. println ( "读线程 " + thread. getName ( ) + " 开始执行 i=" + i) ;
Thread . sleep ( 1000 ) ;
System . out. println ( "读线程 " + thread. getName ( ) + " 结束" ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
} finally {
reentrantReadWriteLock. readLock ( ) . unlock ( ) ;
}
}
public static void write ( Thread thread) {
try {
cyclicBarrier. await ( ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
reentrantReadWriteLock. writeLock ( ) . lock ( ) ;
try {
i++ ;
System . out. println ( "写线程 " + thread. getName ( ) + " 开始执行 i=" + i) ;
System . out. println ( "写线程 " + thread. getName ( ) + " 结束" ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
} finally {
reentrantReadWriteLock. writeLock ( ) . unlock ( ) ;
}
}
public static void main ( String [ ] args) {
executor. execute ( ( ) -> {
write ( Thread . currentThread ( ) ) ;
} ) ;
executor. execute ( ( ) -> {
write ( Thread . currentThread ( ) ) ;
} ) ;
executor. execute ( ( ) -> {
read ( Thread . currentThread ( ) ) ;
} ) ;
executor. execute ( ( ) -> {
read ( Thread . currentThread ( ) ) ;
} ) ;
executor. shutdown ( ) ;
}
}
LockSupport
1.作用
2.方法
线程没有许可证,将当前线程阻塞,直到unpark赋予许可证
默认情况下调用线程不持有许可证,所以被阻塞
让t持有线程与LockSupper 关联的许可证,t线程从park阻塞位置回复运行,解除线程阻塞
若unpark前,该线程因park被挂起,unpark后该线程被唤醒
若unpark前,该线程没有调用park,则unpark后调用park会立即返回