>

等待限时,及使用场景的简单示例

- 编辑:金沙国际平台登录 -

等待限时,及使用场景的简单示例

1. ReentrantLock简介

ReentrantLock也能够叫对象锁,可重入锁,互斥锁。synchronized重量级锁,JDK中期的版本lock比synchronized越来越快,在JDK1.5后头synchronized引进了偏向锁,轻量级锁和千粒重级锁。以至两种锁品质旗鼓十三分,看个人喜好,本文首要介绍一下怎么回顾利用lock。

重入锁可以替代synchronized关键字,在JDK 5.0的从前版本中,重入锁的性质远远好于synchronized ,从6.0开头,JDK在synchronized上做了大气优化,使两岸的属性差距并相当的小.

2.ReentrantLock重入锁lock()

每种线程都能博取相应的lock锁和释放锁unlock,这个锁并不适用分布式蒙受。

package com.test;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Test{public static Lock lock = new ReentrantLock();public String test() throws Exception {lock.lock();try {    //TODO} catch (Exception e) {throw new Exception;} finally {lock.unlock();}return null;}}

 

public class ReenterLock implements Runnable{
    public static ReentrantLock lock = new ReentrantLock();
    public static int i = 0;
    @Override
    public void run() {
        for (int j = 0; j < 10000000; j++) {
            lock.lock();
            try {
                i++;
            }finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) throws Exception{
        ReenterLock rt = new ReenterLock();
        Thread t1 = new Thread(rt);
        Thread t2 = new Thread(rt);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }
}

3.ReentrantLock尝试获得锁有重回值tryLock()

tryLock()方法是有再次回到值的,它象征用来品尝获得锁,倘若获得成功,则赶回true,假诺获得失利(即锁已被其他线程获取),则赶回false,也就说那几个措施无论如何都会及时回去。在拿不到锁时不会直接在那等待。

public class Test{public static Lock lock = new ReentrantLock();public String test() throws Exception {if(lock.tryLock{//尝试获取锁try {//TODO} catch (Exception e) {throw new Exception;} finally {lock.unlock();}}else{//不能获取锁}return null;}}

  

tryLock(long time, TimeUnit unit)方法和tryLock()方法是周围的,只不过差异在于这几个艺术在拿不到锁时会等待一定的年华,在岁月定时之内即使还拿不到锁,就回来false。如若假定一先河得到锁依旧在等候时期内获得了锁,则赶回true。

从代码中得以看看,重入锁能够显示的对代码块举办加锁,释放锁,那样会比synchronized更灵敏,可是急需当心得是,用ReentrantLock 必须手动释放锁.

重入锁的意思: 同贰个线程能够两遍拿走同一把锁,假诺不是重入锁,会发出死锁的情状.
在以下顺序中,子类改写了父类的 synchronized 方法,然后调用父类中的方法,此时只要放置锁不是可重入的,等待叁个千古等不到的锁,那么这段代码将时有产生死锁.

public class Widget{
    public synchronized void doSomething(){
        ........
    }
}

public class LoggingWidget extends Widget{
    public synchronized void doSomething(){
        super.doSomething();
    }
}

重入锁的高端功效:

  • 停顿响应
    对于synchronized来说,假如三个线程正在证带锁,那么结果独有三种情景,要么获得锁继续推行,要么它就保持等待. 而选用重入锁,则提供别的一种大概,那正是线程能够被中断. 这种情景可以减轻相似情状下的死锁难点.
public class DeadLock implements Runnable{

    public static ReentrantLock lock1 = new ReentrantLock();

    public static ReentrantLock lock2 = new ReentrantLock();

    int lock;

    public DeadLock(int lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        try {
            if (lock == 1){
                lock1.lockInterruptibly();
                try {
                    Thread.sleep(500);
                }catch (InterruptedException e){}
                    lock2.lockInterruptibly();

            }else {
                lock2.lockInterruptibly();
                try {
                    Thread.sleep(500);
                }catch (InterruptedException e){}
                    lock1.lockInterruptibly();

            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            if (lock1.isHeldByCurrentThread())
                lock1.unlock();
            if (lock2.isHeldByCurrentThread())
                lock2.unlock();
            System.out.println(Thread.currentThread().getId());
        }
    }

    public static void main(String[] args) throws InterruptedException {
        DeadLock deadLock1 = new DeadLock(1);
        DeadLock deadLock2 = new DeadLock(2);
        Thread t1 = new Thread(deadLock1);
        Thread t2 = new Thread(deadLock2);
        t1.start();
        t2.start();
        Thread.sleep(1000);
        t2.interrupt();

    }
}

在上头程序中,假诺t1 先占用lock1 在挤占lock2,t2 先占用lock2 再据有lock1,很轻巧爆发 : 在t1去占用lock2时,lock2还一直不被假释,可能t2去占用lock1时,lock1还未有被释放.这就能招致等待现象.不过在前后相继最后,将t2线程终止,此时t2线程接收到命令后会中断本人,然后t2释放锁,由t1占用,就能够缓慢解决死锁难题.

  • 有效期等待
    一般性,三个线程拿不到锁,恐怕是因为死锁,也恐怕是因为饥饿,但是倘诺给定多少个等候时间,让线程自动抛弃,就能够化解这一个难题.
    我们得以用tryLock()方法对线程进行限制期限等待的限制.

tryLock()方法有七个参数,第一个是伺机时间长度,第1个是计时单位,假若当先给定时间还一贯不到手锁就能够重回false,要是获得锁就能够回来true. 如以下例子:

public class TimeLock implements Runnable{
    public static ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        try {
            if (lock.tryLock(5, TimeUnit.SECONDS)){
                Thread.sleep(6000);
            }else {
                System.out.println("get lock failed");
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            if (lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        TimeLock timeLock = new TimeLock();
        Thread t1 = new Thread(timeLock);
        Thread t2 = new Thread(timeLock);
        t1.start();
        t2.start();
    }
}

当t1 只怕t2里头二个线程拿到锁现在,会占用锁6分钟,所以第二个线程会在五秒内尝试得到战败.制止了线程等待.
lock.tryLock()也得以用不传递人和参数,代表若是锁未有被别的线程占用就能够回来true,反之重临false.

本文由编程发布,转载请注明来源:等待限时,及使用场景的简单示例