java内置锁的重入_java内置锁synchronized的可重入性

当线程请求一个由其它线程持有的对象锁时,该线程会阻塞,而当线程请求由自己持有的对象锁时,如果该锁是重入锁,请求就会成功,否则阻塞。

java中获取锁的操作的粒度是“线程”,而不是“调用”,即不是每一次调用都是建立一个锁。

重入锁的一种实现方法是为每个锁关联一个线程持有者和计数器,当计数器为0时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法;当某一线程请求成功后,JVM会记下锁的持有线程,并且将计数器置为1;此时其它线程请求该锁,则必须等待;而如果同一个线程再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增;当线程退出同步代码块时,计数器会递减,如果计数器为0,则释放该锁。

看下面的例子,正是由于java的内置锁是可重入的,所以下面这段代码不会发生死锁:

public class Child extends Father{

public static void main(String[] args) {

new Child().doSomething();

}

public synchronized void doSomething(){

System.out.println("child");

super.doSomething();

}

}

class Father{

public synchronized void doSomething(){

System.out.println("Father");

}

}输出结果:

child

Father

上述代码,子类调用doSomething方法时,除了获得自身类锁的同时还会获得父类的锁,如果内置锁不可重入,那调用super.doSomething时就会发生死锁。所以重入就是,你拿了锁,再调用该锁包含的代码可以不用再次等待拿锁。

下面代码主要证明子类调用复写了父类的方法时,除了获得自身类锁的同时还会获得父类的锁:

/**

* 主要为了测试,子类覆盖父类方法后,调用子类方法时,也获取父类的锁

*

*/

public class TestWidget {

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

final LoggingWidget widget = new LoggingWidget();

Thread th1 = new Thread("th1") {

@Override

public void run() {

System.out.println(super.getName() + ":start\r\n");

widget.doSometing();

}

};

Thread th2 = new Thread("th2") {

@Override

public void run() {

System.out.println(super.getName() + ":start\r\n");

/** 为了说明子类复写父类方法后,调用时也持有父类锁*/

widget.doAnother();

/**证明了内置锁对那些没有加synchronized修饰符的方法是不起作用的*/

//widget.doNother();

/**为了说明子类复写父类方法后,调用时也持有父类锁,也持有自己本类的锁*/

// widget.doMyLike();

/**这是两个线程,这是需要等待的,并不是继承的关系,不是重入,重入是发生在一个线程中的*/

//widget.doSometing();

}

};

th1.start();

Thread.sleep(1000);

th2.start();

}

}

class Widget {

public synchronized void doSometing() {

System.out.println("widget ... do something...");

}

public synchronized void doAnother() {

System.out.println("widget... do another thing...");

}

public void doNother() {

System.out.println("widget... do Nothing...");

}

}

class LoggingWidget extends Widget {

@Override

public synchronized void doSometing() {

try {

System.out.println("loggingwidget do something...");

Thread.sleep(5000);

System.out.println("end loggingwidget do something...");

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

super.doSometing();

}

public synchronized void doMyLike() {

System.out.println("loggingwidget do my like...");

}

}

输出结果:

th1:start

loggingwidget do something...

th2:start

end loggingwidget do something...

widget ... do something...

widget... do another thing...

参考资料:http://my.oschina.net/ielts0909/blog/86150

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值