在目前开发的java多线程程序中用的最多的锁就是Synchronized和ReentrantLock,相信大多是童鞋都用过Synchronized但是对ReentrantLock可能了解的不多,下面就详细的对比分析一下两种锁的不同之处和用法
先说Synchronized,这种锁用起来比较简单,这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D)运行完这个方法后再运行此线程A,没有的话,直接运行 它包括两种用法:synchronized 方法和 synchronized 块。 但是容易造成线程的阻塞,导致线程池中最后无线程可用。下面举一个简单的例子
synchronized(syncObject) {
//允许访问控制的代码
通过socket连接另外一台设备(超时时间设为60s)
}
但是这个线程每20秒钟启动一次,那么就会造成线程的堆积。例如,在设备连接中断的情况下,线程T1启动去连接这个设备,那么在超时之前T1是不会释放这个锁的,在20s的时候线程T2启动,然后T2被阻塞,等待T1在60s超时时释放锁,这样循环下去,导致启动的线程越来越多,最后导致系统线程池中的资源耗尽。
而ReentrantLock可以很好的解决这个问题
private Lock lock;
lock = new ReentrantLock(false);
if (lock.tryLock()) {
//若获取锁成功,读取当前sc的数据
try {
//允许访问控制的代码
通过socket连接另外一台设备(超时时间设为60s)
}
}catch(DeviceException de) {
de.printStackTrace();
}finally {
lock.unlock();
}
}
else {
//若获取锁失败,直接放弃本次尝试,接着循环读取列表中下一个sc的数据
//do nothing here, equals to continue loop
}
上面这段代码就很容易的解决了堆积这个问题,例如当线程T1在获得锁之后,线程T2试图去获得锁,如果成功T2就执行try中的代码,如果不成功,T2就放弃获得锁,这样就不会存在线程堆积了。不过记得使用ReentrantLock的话一定记得使用lock.unlock();方法解锁,因为ReentrantLock不会像Synchronized一样自动解锁