前几篇的博文我们谈论过了java多线程的一些概念,java的内存模型,synchronize关键字的使用等,今天我们再来谈谈ReentrantLock锁的使用。关于锁机制,后面我会花很大的篇幅来详细讲解的,现在先看看怎么去使用最简单的Lock,我觉得只有使用好,或者说能熟练的使用然后再去深入的理解往往会事半功倍。
废话不多说,我们就直接进入到正题吧。
1.之前我们说过,为了保证线程安全,我们可以试用Synchronized关键字来保证,那么还有没有其他的方式呢?
当然是有的,那就是加锁,使用java.util.concurrent并发包下的锁,锁的种类有很多,但今天就来认识一下怎么去使用ReentrantLock锁,首先来看看常用的API:
(1)tryLock();------------意思就是尝试去获取锁
(2)tryLock(long time,TimeUnit unit)------给定时间去获取锁
(3)lock();----------------给当前使用对象上锁
(4)unlock();------------释放当前对象的锁
(5)newCondition();---条件或者说一个通知,属于当前所的一个通知
2.那么我们就通过一个例子来说明:
其实ReentrantLock是Lock的实现类,它实现了Lock的部分方法,后面会深入的剖析,现在就单独的讲它的使用(怎么去实现synchronized一样的功能):
(1)首先创建一个方法:methodA
package thread008;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MethodA {
// Lock lock = new ReentrantLock();
// Condition condition = lock.newCondition();
public void methodA(){
try {
// lock.lock();
for(int i=0;i<1000;i++){
System.out.println(i);
}
} finally {
// lock.unlock();
}
}
}
(2)然后创建两个线程:A和B
package thread008;
public class ThreadA extends Thread {
private MethodA m;
public ThreadA(MethodA m) {
this.m = m;
}
public void run(){
m.methodA();
}
}
ThreadB:
package thread008;
public class ThreadB extends Thread {
private MethodA m;
public ThreadB(MethodA m) {
this.m = m;
}
public void run(){
m.methodA();
}
}
先运行看一下结果:(预期的结果应该是打印i的时候会交替的出现)
然后我们再把注释的部分去掉:
结果就跟我们想的一样,一次打印输出,是不是很神奇。这样也实现了synchronized同样的效果。要特别记住的就是一定要关闭锁lock.lock()操作。
可能大家会问,既然都能实现功能,那么我们什么时候用lock,什么时候用synchronized呢?我觉得看应用的环境把。以前的话性能还是lock的好,不过现在随着java的发展synchronized的性能也在不断的提升,未来的路主要还是优化synchronized的使用,所以自己掂量吧,可以通过测试性能去比较。
这篇就介绍到这,下一篇我们再来讲解怎么去实现等待/通知机制,还有Condition怎么使用的。