1、Lock
1)1.5版本之后出现,java.util.concurrent.locks.Lock
2) Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。 锁是控制多个线程对共享资源进行访问的工具。通常,锁提供了对共享资源的独占访问。一次只能有一个线程获得锁,对共享资源的所有访问都需要首先获得锁。不过,某些锁可能允许对共享资源并发访问,如 ReadWriteLock 的读取锁。
3)一般使用的Lock替代synchronized的代码如下:
private Lock l = new ReentrantLock();
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
4)和synchronized一样,也可以在线程之间进行通讯,如下代码:
class Data {
private int number = 0;// 共享变量
private Lock lock = new ReentrantLock(); // 一种互斥锁
private Condition c1 = lock.newCondition(); // 锁上的一个条
private Condition c2 = lock.newCondition(); // 锁上的另一个条件
public Data(){
System.out.println( c1 == c2); // 返回false,一个lock可以拥有多个独立的condition
}
public int increase(){
lock.lock();// 对共享变量的操作必须加锁,而且线程通讯必须在拥有的锁的基础上
try{
if(number != 0){ // 这里没有必要使用循环判断,但是Object.wait必须在循环中判断
try {
c1.await(); // 如果调用c1的方法,那么后面满足条件就应该对应唤醒c1
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number++;
c2.signal(); // 唤醒等待池中的c2
}finally{
lock.unlock(); // 所有的加锁之后的操作都必须使用规定的代码结构来完成
}
return number;
}
public int decrease(){
lock.lock(); // 对共享变量的操作必须加锁,而且线程通讯必须在拥有的锁的基础上
try{
if(number != 1){// 这里没有必要使用循环判断,但是Object.wait必须在循环中判断
try {
c2.await(); // 如果调用c2的方法,那么后面满足条件就应该对应唤醒c2
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number--;
c1.signal(); // 唤醒等待池中的c1
}finally{
lock.unlock();// 所有的加锁之后的操作都必须使用规定的代码结构来完成
}
return number;
}
}
2、Lock 与 synchronized 的比较
1)在JDK 5,Synchronized 要比 Lock 慢很多,但是在 JDK 6 中,它们的效率差不多。
2)Synchronized是Lock的一种简化实现,一个Lock可以对应多个 Condition,而synchronized把Lock和Condition合并了,一个 synchronized Lock只对应一个Condition,可以说Synchronized是Lock 的简化版本。
3)方法对比,使用synchronized的时候都是使用 wait、notify;如果使用Lock,那么需要使用condition的await、singal
3、Lock的一些子类
1)ReentrantLock 一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大,一般情况下我们只要使用这个对象就可以搞定了!
2)ReentrantReadWriteLock.ReadLock 对于一些只读的操作我们可以赋予它共享锁,也就是读锁,可以多个线程同时读数据,但是不能写数据。lock = new ReentrantReadWriteLock().readLock();
3)ReentrantReadWriteLock.WriteLock 对于写操作,那么为了避免脏读,所以我们应该给他加排它锁,这样只能写,不能读,lock = new ReentrantReadWriteLock.WriteLock();
来源:oschina
链接:https://my.oschina.net/u/1989321/blog/505522