ReentrantLock的一个问题

来源:互联网 发布:淘宝售后外包 编辑:程序博客网 时间:2024/06/06 23:50

今天在回顾java并发编程时遇到一个问题,有点奇怪
代码如下

class BlockMutex {    private Lock lock = new ReentrantLock();    public BlockMutex() {        lock.lock();    }    public void f(String name) {        lock.lock();        System.out.println(name+" lock acquired in f() ");    }}

BlockMutex是一个可能存在并发问题的资源,所以我使用lock以实现同步,创建该对象的线程在创建的时候就会持有对象锁,如构造器,在执行f()方法时候也要先申请锁

class BlockThread implements Runnable {    //线程创建BlockThread同时就持有了blockMutex锁    private BlockMutex blockMutex = new BlockMutex();    public BlockMutex getBlockMutex() {        return blockMutex;    }    @Override    public void run() {        System.out.println("waiting lock in f()");        blockMutex.f("BlockThread");        System.out.println("broken out of blocked call");    }}

这是一个Task task初始化的时候,该task就会持有锁,当task执行run方法的时候,会执行f()函数,因为BlockThread会初始化BlockMutex时就持有了BlockMutex的对象锁,而ReentrantLock是支持重入的,所以BlockThread理所应当继续执行f()方法

public static void main(String[] args) throws InterruptedException {        BlockThread blockThread=new BlockThread();        Thread thread = new Thread(blockThread);        thread.start();        TimeUnit.SECONDS.sleep(1);        System.out.println("main has finished ");    }

在main函数中进行测试
运行结果如下

waiting lock in f()main has finished 

我感觉奇怪的是blockThread线程在执行时竟然一直阻塞在f()方法中,按理说BlockThread已经持有了BlockMutex的对象锁,不应该继续申请锁.经过一段时间思考后我明白了blockThread线程并没有持有BlockMutex的对象锁,blockThread初始化是在主线程中进行,而锁的申请是在构造器中完成,所以持有BlockMutex的对象锁是主线程,为了验证这一思想,我们只要让主线程执行f()方法,如果无等待执行成功则我们这一思想成立,更改main函数如下

public class LockInterruptTest {    public static void main(String[] args) throws InterruptedException {        BlockThread blockThread=new BlockThread();        Thread thread = new Thread(blockThread);        blockThread.getBlockMutex().f("main");        thread.start();        TimeUnit.SECONDS.sleep(1);        System.out.println("main has finished ");    }}

运行结果

main lock acquired in f() waiting lock in f()main has finished 

猜想成立

原创粉丝点击