Lock接口中的几个方法讨论

来源:互联网 发布:sql plus 登录 编辑:程序博客网 时间:2024/05/27 19:26

显示锁Lock和ReentrantLock

Lock 是一个接口,提供了无条件的、可轮询的、定时的、可中断的锁获取操作,所有加锁和解锁的方法都是显示的。核心方法有lock()、unlock()、tryLock(),实现类有ReentrantLock、ReentrantReadWriteLock.ReadLock、ReentrantReadWriteLock.WriteLock

void lock()
拿不到lock就不罢休,不然线程就一直block,调用方法结束后,要是用unlock,否则会造成死锁

代码结构示例:

public void m(){        lock.lock();        try {        } catch (Exception e) {            // TODO: handle exception        }finally{            lock.unlock();        }    }

boolean tryLock()
马上返回,拿到lock就返回true,不然返回false;通常对于那种不必获取锁的操作可能有用,注意必须拿到锁的方法才可调用unlock()方法

import java.util.concurrent.locks.ReentrantLock;public class LockTest {    ReentrantLock lock = new ReentrantLock();    public void tryLockTest(){        try {            boolean getLock = lock.tryLock();            if(getLock){                System.out.println("Thead----"+Thread.currentThread().getName()+"---get lock---");                Thread.sleep(10);                lock.unlock();//必须拿到锁的线程才可调用此方法,否则抛异常            }else{                System.out.println("Thead----"+Thread.currentThread().getName()+"---not get lock---");                Thread.sleep(10);            }               }catch(Exception e){            System.out.println(Thread.currentThread().getName()+"异常");            e.printStackTrace();        }    }}

运行结果:
这里写图片描述

由结果可以看出,只有第一个线程获取到锁。

boolean tryLock(long ParamLong,TimeUnit ParamTimeUnit) throws InterruptedException

带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false

这里写图片描述

图中画红框部分是经修改的代码,修改后的执行结果如下

这里写图片描述

当线程没有拿到lock,要等一会,超时后仍没有拿到,才会返回false

void lockInterruptibly() throws InterruptedException

优先考虑响应中断,而不是响应锁定的普通获取,当外部线程被Interrupted,则当线程调用lockInterruptibly时进入catch方法中,若外部线程没有被打断,则与功能与调用lock方法一致

代码进行如下修改

子方法中调用lockInterruptibly()

这里写图片描述

主方法中,将一些线程打断
这里写图片描述

下面我们看一下执行结果
这里写图片描述

Lock与synchronized比较
1、lock使用起来更加灵活,但是必须有释放锁的动作配合
2、lock适用于代码块,而synchronized是对象之间的互斥锁

注意以下两种方式的区别

第一种方式:两个方法之间的锁是独立的

public class MainT {    /**     * @param args     */    public static void main(String[] args) {        final LockTest lt = new LockTest();        //final LockTest lt2 = new LockTest();        // TODO Auto-generated method stub        for(int i=0;i<2;i++){            Thread t1=new Thread(new Runnable() {                @Override                public void run() {                    // TODO Auto-generated method stub                    lt.get();                }            });            t1.start();        }        for(int i=0;i<2;i++){            Thread t1=new Thread(new Runnable() {                @Override                public void run() {                    // TODO Auto-generated method stub                    lt.put();                }            });            t1.start();        }    }}
import java.util.concurrent.locks.ReentrantLock;public class LockTest {    public  void get(){        ReentrantLock lock = new ReentrantLock();        try {            lock.lock();            System.out.println(Thread.currentThread().getName()+"----get begin---");            Thread.sleep(1000);//模仿干活            System.out.println(Thread.currentThread().getName()+"----get end---");            lock.unlock();        } catch (Exception e) {            // TODO: handle exception        }    }    public void put(){        ReentrantLock lock = new ReentrantLock();        try {            lock.lock();            System.out.println(Thread.currentThread().getName()+"----put begin---");            Thread.sleep(1000);//模仿干活            System.out.println(Thread.currentThread().getName()+"----put end---");            lock.unlock();        } catch (Exception e) {            // TODO: handle exception        }    }}

每个调用此方法的锁都是独立的,没有起到锁的用途

第二种方式:两个方法之间使用相同的锁

    /**     * @param args     */    public static void main(String[] args) {        final LockTest lt = new LockTest();        // TODO Auto-generated method stub        for(int i=0;i<2;i++){            Thread t1=new Thread(new Runnable() {                @Override                public void run() {                    // TODO Auto-generated method stub                    lt.get();                }            });            t1.start();        }        for(int i=0;i<2;i++){            Thread t1=new Thread(new Runnable() {                @Override                public void run() {                    // TODO Auto-generated method stub                    lt.put();                }            });            t1.start();        }    }}
import java.util.concurrent.locks.ReentrantLock;public class LockTest {    ReentrantLock lock = new ReentrantLock();    public  void get(){        try {            lock.lock();            System.out.println(Thread.currentThread().getName()+"----get begin---");            Thread.sleep(1000);//模仿干活            System.out.println(Thread.currentThread().getName()+"----get end---");            lock.unlock();        } catch (Exception e) {            // TODO: handle exception        }    }    public void put(){        try {            lock.lock();            System.out.println(Thread.currentThread().getName()+"----put begin---");            Thread.sleep(1000);//模仿干活            System.out.println(Thread.currentThread().getName()+"----put end---");            lock.unlock();        } catch (Exception e) {            // TODO: handle exception        }    }}

两个线程调用方法使用的同一个锁,所以串行执行;结果如下图所示
这里写图片描述

0 0