多线程之——重入锁

重入锁 reentrantLocksynchronized关键字相比的优势是他更加灵活,可以在任何需要的地方加锁或者释放锁。下面用这两种方式进行同步控制。

//使用重入锁

public void run() {

        for (int j = 0; j < 100000; j++) {

        //lockReentrantLock的一个实例

            lock.lock();

            try {

                i++;

            } finally {

                lock.unlock();

            }

        }

}

//使用synchronized关键字

public void run() {

        for (int j = 0; j < 100000; j++) {

        synchronized(lock){

                i++;

        }

}

 

两者都能在多线程的情况下保证数据的原子性,但是显然重入锁的方式更加灵活。此外重入锁可以响应中断,看下面的例子。

 

首先我们实例化两个重入锁类变量lock1,lock2,然后用线程1先获得lock1的锁,再获得lock2的锁。线程2则先获得lock2的锁再获得lock2的锁。这样会导致死锁。此时我们可以中断线程2,使得线程2释放lock2,并退出,而线程1可以获得lock2的锁。这就体现了重入锁的一个优点:响应中断。

//测试代码

import java.util.concurrent.locks.ReentrantLock;

 

/**

 * Created by owen on 2017/3/10.

 */

public class IntLock implements Runnable {

    public static ReentrantLock lock1 = new ReentrantLock();

    public static ReentrantLock lock2 = new ReentrantLock();

    int lock;

 

    public IntLock(int lock){

        this.lock = lock;

    }

 

    @Override

    public void run(){

        try{

            if(lock ==1) {

                lock1.lockInterruptibly();

                Thread.sleep(500);

                lock2.lockInterruptibly();

            }

            else{

                lock2.lockInterruptibly();

                Thread.sleep(500);

                lock1.lockInterruptibly();

            }

        }catch (InterruptedException e){

            e.printStackTrace();

        }finally {

            if(lock1.isHeldByCurrentThread()){

                lock1.unlock();

            }

            if(lock2.isHeldByCurrentThread()){

                lock2.unlock();

            }

            try {

                Thread.sleep(1000);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

            System.out.println(Thread.currentThread().getId()+"线程退出");

        }

    }

 

    public static void main(String[] args) throws InterruptedException {

        IntLock l1 = new IntLock(1);

        IntLock l2 = new IntLock(2);

        Thread t1 = new Thread(l1);

        Thread t2 = new Thread(l2);

        t1.start();

        t2.start();

        Thread.sleep(4000);

        t2.interrupt();

    }

}

 

注意到重入锁申请获得锁的方式是使用lockInteruptibly()方法而不是方法,这是因为lockInteruptibly()方法优先响应中断而不是优先申请锁。而lock()方法则相反。

文档里面对lockInteruptibly()方法的一个说明是这样的:

In this implementation, as this method is an explicit interruption point, preference is given to responding to the interrupt over normal or reentrant acquisition of the lock.

 

待续。

posted @ 2017-03-10 15:19  玫瑰色的你  阅读(212)  评论(0编辑  收藏  举报