Java SE5之后,并发包中新增Lock接口用来实现锁功能,提供与synchronized关键字类似的同步功能,并且在使用的时候可以显式的获取和释放锁。
实例代码:
Lock lock = new ReentrantLock(); //重入锁
lock.lock(); //获取锁
try{
//
}finally{
lock.unlock(); //释放锁
}
其它接口,
lockInterruptibly() 可中断的获取锁,与lock()方法的不同之处在于该方法会响应中断,即在锁的获取过程中可以中断当前线程。
tryLock() 尝试非阻塞的获取锁。该方法立刻返回,如果能够获取则返回true,否则返回false
tryLock(long time, TimeUnit unit) 超时获取锁。在指定的截止时间之前获取锁,如果截止时间到了仍旧无法获取所,则返回false。
Lock.newCondition() 获取等待通知组件,该组件和锁绑定,当前线程只有获取到了锁,才能调用该组件的wait()方法,而调用后,当前线程将所释放。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void await(){
//lock.lock();
try{
lock.lock();
System.out.println("await时间为: " + System.currentTimeMillis());
condition.await();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void siginal(){
try{
lock.lock();
System.out.println("siginal时间为: " + System.currentTimeMillis());
condition.signal();//condition.signalAll();
}finally{
lock.unlock();
}
}
condition.await类似于Object类的wait方法
condition.siginal类似于Object类的notify方法
condition.siginalAll类似于Object类的notifyAll方法
如果需要单独唤醒某个线程,则需要创建多个condition,然后对指定condition唤醒。
利用ReentrantLock实现1对1生产者/消费者模式
public class MyService {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private boolean hasValue = false;
public void set() throws InterruptedException{
try{
lock.lock();
System.out.println("set lock begin");
if(hasValue == true){
condition.await();
}
System.out.println("生产一个value");
condition.signal();
hasValue = true;
}finally{
System.out.println("set unlock now");
lock.unlock();
}
}
public void get() throws InterruptedException{
try{
lock.lock();
System.out.println("get lock begin");
if(hasValue == false){
condition.await();
}
System.out.println("消费一个value");
condition.signal();
hasValue=false;
}finally{
System.out.println("get unlock now");
lock.unlock();
}
}
}
//生产者线程
public class MySetThread extends Thread{
private MyService service;
public MySetThread(MyService service){
this.service = service;
}
@Override
public void run() {
try {
for(int i=0;i<5;i++)
service.set();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//消费者线程
public class MyGetThread extends Thread{
private MyService service;
public MyGetThread(MyService service){
this.service = service;
}
@Override
public void run() {
try {
for(int i=0;i<5;i++)
service.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//测试代码
public static void main(String[] args) {
MyService service = new MyService();
MySetThread a = new MySetThread(service);
a.start();
MyGetThread b = new MyGetThread(service);
b.start();
}
利用ReentrantLock实现多个生产者和消费者的模式
测试代码:
public static void main(String[] args) {
MyService service = new MyService();
MySetThread[] threadSets = new MySetThread[10];
MyGetThread[] threadGets = new MyGetThread[10];
for(int i=0;i<10;i++){
threadSets[i] = new MySetThread(service);
threadGets[i] = new MyGetThread(service);
threadSets[i].start();
threadGets[i].start();
}
}
则需要将之前的condition.singal()改为condition.singalAll()
公平锁与非公平锁
公平锁表示县城获取锁的顺序是按照线程加锁的顺序类分配的,即先来先得的FIFO先进先出顺序。而非公平锁就是一种获取锁的抢占机制,是随机获取锁的。
Lock lock = new ReentrantLock(isFair);