Lock接口中的几个方法讨论

显示锁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
        }
    }
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值