synchronized细节问题(一)
synchronized锁重入:
关键字synchronized拥有锁重入的功能,也就是在使用synchronized时,当一个线程得到一个对象的锁后,再次请求此对象时是可以再次得到该对象的锁。
下面看一段锁重入的小demo:
public class SyncDubbo1 {
public synchronized void method1() {
System.out.println("method1..");
method2();
}
public synchronized void method2() {
System.out.println("method2..");
method3();
}
public synchronized void method3() {
System.out.println("method3..");
}
public static void main(String[] args) {
final SyncDubbo1 sd = new SyncDubbo1();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
sd.method1();
}
});
t1.start();
}
}
这中方式的调用是没有任何问题的,运行的结果是
method1..
method2..
method3..
这是一个最简单的锁重入的问题,是完全没有任何问题的。
下面看一个稍微复杂点的锁重入的代码:
public class SyncDubbo2 {
static class Main {
public int i = 10;
private synchronized void operationSup() {
try {
i--;
System.out.println("Main print i = " + i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Sub extends Main {
public synchronized void operationSub() {
try {
while (i > 0) {
i--;
System.out.println("Sub print i = " + i);
Thread.sleep(100);
this.operationSub();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
Sub sub = new Sub();
sub.operationSub();
}
});
}
}
运行结果是:
Sub print i = 9
Main print i = 8
Sub print i = 7
Main print i = 6
Sub print i = 5
Main print i = 4
Sub print i = 3
Main print i = 2
Sub print i = 1
Main print i = 0
这个结果是没有任何问题的,通过这个例子是想说明,再有父子继承关系的时候,然后都加synchronized修饰时,这样去调用也是线程安全的。这是对于synchronized应用的第二种形式。
下面在看一个synchronized中修饰的方法里面,碰到某些异常时,出现的情况,下面也看一个demo;
public class SyncException {
private int i = 0;
public synchronized void operation() {
while (true) {
try {
i++;
Thread.sleep(200);
System.out.println(Thread.currentThread().getName() + " ,i = " + i);
if (i == 5) {
Integer.parseInt("a");
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(" log info i = " + i);
}
}
}
public static void main(String[] args) {
final SyncException se = new SyncException();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
se.operation();
}
},"t1");
t1.start();
}
}
这段代码在i=5的时候代码发生异常,这种情况下,synchronized会自动解锁,程序会继续执行,发生异常的情况下,我们一定要对异常情况进行处理,运行的结果是:
t1 ,i = 1
t1 ,i = 2
t1 ,i = 3
t1 ,i = 4
t1 ,i = 5
log info i = 5
java.lang.NumberFormatException: For input string: "a"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:492)
at java.lang.Integer.parseInt(Integer.java:527)
at Thread.SyncException.operation(SyncException.java:16)
at Thread.SyncException$1.run(SyncException.java:31)
at java.lang.Thread.run(Thread.java:744)
t1 ,i = 6
t1 ,i = 7
t1 ,i = 8
在实际开发中,对 这种异常有两种方式的处理,第一种就是上面写的这种,catch到异常后,把对应的数据记录到日志,当然有个前提条件,就是每次去执行这个任务之间都是没有关联的;还有一种情况,执行的任务是有关联的,是一个整体,假如采用前面那种情况,在异常发生后的几次情况的执行都是有问题的,这也有一个解决方法,就是补或一个打断异常,InterruptedException,或者抛出一个运行时异常,就能停止这个线程。
总结:对于web应用程序,异常释放锁的情况,如果不及时处理,很可能对你的应用程序业务逻辑产生严重的错误,比如你现在执行一个队列任务,很多对象都去在等待第一个对象正确执行完毕再去释放锁,但是第一个对象由于异常的出现,导致业务逻辑没有正常执行完毕,就释放了锁,那么可想而知后续的对象执行的都是错误的逻辑。所以这一点一定要引起注意,在编写代码的时候,一定要考虑周全。
synchronized细节问题(一)的更多相关文章
- 5.并发编程-synchronized 细节说明
并发编程-synchronized 细节说明 1. synchronized-锁重入 & 异常释放锁 说明 * 关键字synchronized 拥有锁重入的功能,也就是在使用synchroni ...
- 架构师养成记--3.synchronized细节问题
一.synchronized有锁重入的特点,某个线程得到对象的锁后,再次请求此对象可以再次得到改对象的锁.如下示例,在method1中调用method2,在method2中调用method3,而met ...
- synchronized细节问题
一.synchronized有锁重入的特点,某个线程得到对象的锁后,再次请求此对象可以再次得到改对象的锁.如下示例,在method1中调用method2,在method2中调用method3,而met ...
- synchronized细节问题(二)
使用synchronized声明的方法在某些情况下是有弊端的,比如A线程调用同步的方法执行一个很长时间的任务,那么B线程就必须等待比较长的时间才能执行,这样的情况下,可以使用synchronized代 ...
- 同步中的四种锁synchronized、ReentrantLock、ReadWriteLock、StampedLock
目录 1.synchronized同步锁 2.ReentrantLock重入锁 3.ReadWriteLock读写锁 4.StampedLock戳锁(目前没找到合适的名字,先这么叫吧...) 5.总结 ...
- 同步中的四种锁synchronized、ReentrantLock、ReentrantReadWriteLock、StampedLock
为了更好的支持并发程序,JDK内部提供了多种锁.本文总结4种锁. 1.synchronized同步锁 使用: synchronized本质上就2种锁: 1.锁同步代码块 2.锁方法 可用object. ...
- 对象、对象监视器、同步队列、执行线程关系(synchronized的实现细节或原理)
synchronized在使用的时候底层细节你了解吗,相信很多同学对细节很少关注:比如竞争失败了的线程怎么安置,每个对象的监视器,线程执行synchronized时,其实是获取对象的监视器才能进入同步 ...
- java线程之——synchronized的注意细节
我在学习synchronized的时候,十分好奇当一个线程进入了一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 然后就做了个实验(实验代码最后贴出),最后得到了如下 ...
- Java语法细节 - synchronized和volatile
目录 synchronized关键字 关键字volatile synchronized关键字 synchronized关键字锁住方法和this的不同之处: public synchronized vo ...
随机推荐
- linux 文件目录类的指令 包含查找
pwd :显示当前目录的绝对路径 ls : 显示当前目录 -a 显示所有文件 包括隐藏文件 -l 以列表的方式进行显示 cd 切换目录 cd ~ :返回家目录 cd .. :返回上一级的目录 m ...
- css样式表1
1内联样式表 和html联合使用,控制精确,但是可重用性差,冗余多. <p style="font-size:14px;"></p> <div sty ...
- 【382】利用 namedtuple 实现函数添加属性
namedtuple 能够实现类似类的效果,tuple 的元素可以通过属性的形式返回,如下所示: from collections import namedtuple Student = namedt ...
- delphi 原创应用工具箱
用到的主要知识点: (1) listview背景透明 (2) 读取应用图标 (3)图标透明 (4)实时显示微软必应首页图,裁剪图片等
- git-02 下载代码
- 为了显示此页面,Firefox 必须发送将重复此前动作的数据(例如搜索或者下订单)
火狐浏览器重新加载页面出现下面提示,必须要点击“重新发送”才能完成刚才的请求: 这个是火狐的一个提示功能主要是防止同一页面的数据反复提交: 解决方法: 不要用location.reload();来刷新 ...
- js高级-变量内存分析
var a = 9, b, c={age:9}, d; b = a; b = 19; console.log(a) console.log(b) d = c; d.age = 22; console ...
- ADO.Net 综合练习题
题目: 第一部分: 新建一个数据库:ADO测试,包含下面两个数据表,使用代码创建,并保留创建的代码文本. 专业表Subject: 专业编号(SubjectCode):nvarchar类型,不能为空,主 ...
- mysql查找某连续字段中断的编号
查询dj_pxlb表中zwh 空缺的值 select model2.zwh-1 as kqzwh from (select model1.zwh from dj_pxlb as model1 wher ...
- openssl 生成证书
nginx生成证书,一共四步 1) 生成RSA私钥 (会要求输入至少4位密码)# openssl genrsa -des3 -out private.key 2048 # 2) 根据已生成的RSA私钥 ...