1.synchronized和lock 都有可重入性.
2.synchronized和lock 都可以知道线程是否持有了锁(看到很多文章说只有lock可以判断是否获取到锁,其实是错误的,synchronized也可以获取. synchronized 用Thread.holdsLock来判断).
3.synchronized在进入锁池后,会不停得等待直到获取锁对象,无法中断,是真爱.而lock可以设置等待时间停止锁竞争.
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
还可以用lock.lockInterruptibly()
方法:当无法获取到锁的时候,直接中断,进行异常处理.
4.synchronized是内置的,而lock是一个接口.
5.synchronized在运行结束后或者异常后会自动释放锁,而lock需要自己手动释放锁
lock.unlock();
6.synchronized是非公平锁,而lock可以是非公平锁也可以是公平锁.用布尔值来选择类型.
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
7.lock还有读写锁,
读-读不互斥,
读-写互斥,
写-写互斥.
写锁还可以不用unlock降级为读锁
知识点: 读写锁经典案例,防缓存系统
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockTest {
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
Map<String,Object> cache = new HashMap<String,Object>();
public Object get(String key){
Object value = null;
try {
rwl.readLock().lock();
value = cache.get(key);
if(null==value){
rwl.readLock().unlock();//释放都锁,获取写锁
try {
rwl.writeLock().lock();
//获取写锁后再次判断对象是否为null,方式下一个等待的写线程进入后直接获取数据去
value = cache.get(key);
if(null==value){
System.out.println(Thread.currentThread().getName());
value="aaaaa";//实际操作代码从数据库中查询得到的对象
cache.put(key, value);
}
//自身锁降级为都锁
rwl.readLock().lock();
} catch (Exception e) {
// TODO: handle exception
}finally{
rwl.writeLock().unlock();//释放写锁
}
}
} catch (Exception e) {
// TODO: handle exception
}finally{
rwl.readLock().unlock();
}
return value;
}
}
import java.util.HashMap;
import java.util.Map;
public class MainReadWritLockTest {
Map<String,Object> cache = new HashMap<String,Object>();
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
final ReadWriteLockTest rwlt = new ReadWriteLockTest();
for(int i=0; i<10;i++){
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Object value= rwlt.get("id");
System.out.println(Thread.currentThread().getName()+"--"+value);
}
}).start();
}
}
}