Jdk1.5中,在Java.util.concurrent.locks包下,有一组实现线程同步的接口和类,说到线程的同步,很多立马就会想到synchronized关键字,这是java内置的关键字,用来处理线程同步的,但这个关键字有很多的缺陷,使用起来也不是很方便和直观,所以就出现了Lock,下面,我们就来对比着讲解Lock。
synchronized关键字:
该关键字在使用的过程中会有如下几个问题:
1、不可控性,无法做到随心的加锁和释放锁
2、效率比较低下,比如我们现在并发的读两个文件,读与读之间是互不影响的,但如果给这个读的对象使用synchronized来实现同步的话,那么只要有一个线程进入了,那么其他的线程都要等待。
3、无法知道线程是否获取到了锁
以上问题,Lock都可以很好的解决,并且jdk1.5还提供了各种锁,例如读写锁,但有一点需要注意,使用synchronized关键时,无须手动释放锁,但使用Lock必须手动释放锁。下面我们就来学习一下Lock锁。
Lock是一个上层的接口,其原型如下,总共提供了6个方法:
- public interface Lock {
-
- void lock();
-
- void lockInterruptibly() throws InterruptedException;
-
- boolean tryLock();
-
- boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
-
- void unlock();
-
- Condition newCondition();
- }
那么这几个方法该如何使用了?前面我们说到,使用Lock是需要手动释放锁的,但是如果程序中抛出了异常,那么就无法做到释放锁,有可能引起死锁,所以我们在使用Lock的时候,有一种固定的格式,如下:
-
- Lock l = ...;
- l.lock();
- try {
-
- } finally {
- l.unlock();
- }
下面我们来看一个简单的例子,代码如下:
-
-
-
- public class LockDemo {
-
- Lock lock = new ReentrantLock();
- public void readFile(String fileMessage){
- lock.lock();
- try{
- System.out.println(Thread.currentThread().getName()+"得到了锁,正在读取文件……");
- for(int i=0; i<fileMessage.length(); i++){
- System.out.print(fileMessage.charAt(i));
- }
- System.out.println();
- System.out.println("文件读取完毕!");
- }finally{
- System.out.println(Thread.currentThread().getName()+"释放了锁!");
- lock.unlock();
- }
- }
-
- public void demo(final String fileMessage){
-
- ExecutorService service = Executors.newCachedThreadPool();
-
- for(int i=0; i<20; i++){
- service.execute(new Runnable() {
- @Override
- public void run() {
- readFile(fileMessage);
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- });
- }
-
- service.shutdown();
- }
- }
我们先把锁的那两行代码注释掉,看下效果如何:
然后我们把锁的代码加上,看下效果如何:
如果我们把上面的readFile方法前面加上synchronized关键字,然后把锁去掉,效果是一样的。
tryLock锁的使用和Lock锁的使用类似,下面把示例代码贴出来,就不做过多的说明了,代码如下:
-
-
-
- public class TryLockDemo {
-
- Lock lock = new ReentrantLock();
- public void readFile(String fileMessage){
- if(lock.tryLock()){
- try{
- System.out.println(Thread.currentThread().getName()+"得到了锁,正在读取文件……");
- System.out.println("文件读取完毕!");
- }finally{
- System.out.println(Thread.currentThread().getName()+"释放了锁!");
- lock.unlock();
- }
- }else{
- System.out.println(Thread.currentThread().getName()+"获取锁失败!");
- }
- }
-
- public void demo(final String fileMessage){
-
- ExecutorService service = Executors.newCachedThreadPool();
-
- for(int i=0; i<200; i++){
- service.execute(new Runnable() {
- @Override
- public void run() {
- readFile(fileMessage);
- }
- });
- }
-
- service.shutdown();
- }
- }
测试效果如下: