Java中的ReentrantLock

Java中的ReentrantLock基本功能与synchronized代码块相当,但是提供了一些高级特性。

首先来看一下ReentrantLock的基本使用:

public class LockTest {

    ReentrantLock mLock = new ReentrantLock();

    int num = 0;

    Runnable mRunnableOne = new Runnable() {
        @Override
        public void run() {
            mLock.lock();
            System.out.println("ThreadOne: start");
            try {
                for (int m = 0; m < Integer.MAX_VALUE; m++) {
                    num++;
                }
                System.out.println("ThreadOne: over");
            } finally {
                mLock.unlock();
            }
        }
    };

    Runnable mRunnableTwo = new Runnable() {
        @Override
        public void run() {
            mLock.lock();
            System.out.println(num);
            mLock.unlock();
        }
    };

    public static void main(String[] args) {
        LockTest test = new LockTest();
        Thread a = new Thread(test.mRunnableOne);
        Thread b = new Thread(test.mRunnableTwo);

        a.start();
        b.start();
    }
}

在这段程序中,我们定义了两个Runnable,第一个线程获得锁,循环将变量num值+1,第二个线程尝试获得锁,并打印num的值。
运行这段程序,会输出:

ThreadOne: start
ThreadOne: over
2147483647

可以看到线程2一开始无法获得锁,需等待线程1执行完毕后,才可打印num的数值。

下面来看看ReentrantLock的一些特性。
1.ReentrantLock允许同一个线程多次调用lock接口获取锁,每调用一次计数便加一。因此在释放锁的时候必须调用相应多次数unlock才能释放锁:

package study.threadtest;

import java.util.concurrent.locks.ReentrantLock;

public class LockTest {
    ......

    Runnable mRunnableOne = new Runnable() {
        @Override
        public void run() {
            mLock.lock();
            mLock.lock();
            System.out.println("ThreadOne: start");
            try {
                for (int m = 0; m < Integer.MAX_VALUE; m++) {
                    num++;
                }
                System.out.println("ThreadOne: over");
            } finally {
                mLock.unlock();
            }
        }
    };
    ......

}

我们对线程一做一下修改,多调用一次lock接口。程序运行后输出:

ThreadOne: start
ThreadOne: over

可见由于调用unlock次数不够,线程2并不能获取到锁,因此无法输出打印。

2.synchronized在获取不到锁的时候会一直阻塞,直到这个线程获取到锁才继续执行。由上面的例子可以看到ReentrantLock的lock接口也是这样的,旦ReentrantLock同时还提供了一个tryLock接口,它允许线程尝试获取锁,如果无法获得锁,就执行其他的逻辑,而不是一直阻塞等待。

public class LockTest {

    ReentrantLock mLock = new ReentrantLock();

    int num = 0;

    Runnable mRunnableOne = new Runnable() {
        @Override
        public void run() {
            mLock.lock();
            System.out.println("ThreadOne: start");
            try {
                for (int m = 0; m < Integer.MAX_VALUE; m++) {
                    num++;
                }
                System.out.println("ThreadOne: over");
            } finally {
                mLock.unlock();
            }
        }
    };

    Runnable mRunnableTwo = new Runnable() {
        @Override
        public void run() {
            if (mLock.tryLock()) {
                System.out.println(num);
                mLock.unlock();
            } else {
                System.out.println("ThreadTwo: Do something else");
            }
        }
    };

    public static void main(String[] args) {
        LockTest test = new LockTest();
        Thread a = new Thread(test.mRunnableOne);
        Thread b = new Thread(test.mRunnableTwo);

        a.start();
        b.start();
    }
}

我们在线程2中使用tryLock尝试获取锁,如果不能获取,则执行else中的逻辑。运行代码可以看到输出:

ThreadOne: start
ThreadTwo: Do something else
ThreadOne: over
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值