synchronized细节问题
一、synchronized有锁重入的特点,某个线程得到对象的锁后,再次请求此对象可以再次得到改对象的锁。如下示例,在method1中调用method2,在method2中调用method3,而method1、method2和method3都是加了synchronized关键字的。
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();
}
}
二、父类和子类的方法都是synchronized的,在子类的方法中调用父类的方法,也是线程安全的。
public class SyncDubbo2 {
static class Main {
public int i = 10;
public 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.operationSup();
}
} 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();
}
});
t1.start();
}
}
执行结果:

三、synchronized方法内抛异常怎么处理
锁会自动释放
throw RuntimeException打断此线程或者记录日志然后continue,选择哪种方案取决于具体业务要求。
public class SyncException {
private int i = 0;
public synchronized void operation(){
while(true){
try {
i++;
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " , i = " + i);
if(i == 20){
//Integer.parseInt("a");
throw new RuntimeException();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
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();
}
}
四、synchronized代码块锁,实用起来也会比较灵活
this、class、Object都可以用来作为代码块锁
public class ObjectLock {
public void method1(){
synchronized (this) { //对象锁
try {
System.out.println("do method1..");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void method2(){ //类锁
synchronized (ObjectLock.class) {
try {
System.out.println("do method2..");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private Object lock = new Object();
public void method3(){ //任何对象锁
synchronized (lock) {
try {
System.out.println("do method3..");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
final ObjectLock objLock = new ObjectLock();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
objLock.method1();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
objLock.method2();
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
objLock.method3();
}
});
t1.start();
t2.start();
t3.start();
}
}
五、尽量不要用String常量作为锁
如下代码只会有t1线程运行,但可以new一个String对象。
public class StringLock {
public void method() {
//new String("字符串常量")
synchronized ("字符串常量") {
try {
while(true){
System.out.println("当前线程 : " + Thread.currentThread().getName() + "开始");
Thread.sleep(1000);
System.out.println("当前线程 : " + Thread.currentThread().getName() + "结束");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
final StringLock stringLock = new StringLock();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
stringLock.method();
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
stringLock.method();
}
},"t2");
t1.start();
t2.start();
}
}
六、一个对象被用作锁时,这个对象内的属性发生变化不会影响锁的使用。
public class ModifyLock {
private String name ;
private int age ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public synchronized void changeAttributte(String name, int age) {
try {
System.out.println("当前线程 : " + Thread.currentThread().getName() + " 开始");
this.setName(name);
this.setAge(age);
System.out.println("当前线程 : " + Thread.currentThread().getName() + " 修改对象内容为: "
+ this.getName() + ", " + this.getAge());
Thread.sleep(2000);
System.out.println("当前线程 : " + Thread.currentThread().getName() + " 结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
final ModifyLock modifyLock = new ModifyLock();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
modifyLock.changeAttributte("张三", 20);
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
modifyLock.changeAttributte("李四", 21);
}
},"t2");
t1.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
}
}
synchronized细节问题的更多相关文章
- 5.并发编程-synchronized 细节说明
并发编程-synchronized 细节说明 1. synchronized-锁重入 & 异常释放锁 说明 * 关键字synchronized 拥有锁重入的功能,也就是在使用synchroni ...
- 架构师养成记--3.synchronized细节问题
一.synchronized有锁重入的特点,某个线程得到对象的锁后,再次请求此对象可以再次得到改对象的锁.如下示例,在method1中调用method2,在method2中调用method3,而met ...
- synchronized细节问题(二)
使用synchronized声明的方法在某些情况下是有弊端的,比如A线程调用同步的方法执行一个很长时间的任务,那么B线程就必须等待比较长的时间才能执行,这样的情况下,可以使用synchronized代 ...
- synchronized细节问题(一)
synchronized锁重入: 关键字synchronized拥有锁重入的功能,也就是在使用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 ...
随机推荐
- android.database.CursorIndexOutOfBoundsException: Index <m> requested, with a size of <n>
遇到这样的问题比较郁闷,造成上述问题的原因也是多种多样的. 总结一下原因: 1:得到cursor对象,没有moveToPosition()或者moveToNext()等游标操作就进行cursor.ge ...
- myeclipse乱码问题和 编码设置
A Myeclipse安装后编码默认是GB18030,外面的人一般推荐用UTF-8.如果在导入项目后发现乱码现象,那是编码设置设置不对. Eclipse 编码设置: 全局编码设置:编码设置的方法 ...
- 浅谈 JavaScript new 执行过程及function原理
前言 最近在学习JavaScript语言精粹,感觉写得相当不错.所以这里也算是总结一下.一个方法使用new的方式创建到底是怎样的过程,一个function的声明内部又是怎样执行的呢 另外学的过程中,不 ...
- JQuery基础知识(1)
JQuery基础知识(1) 对JQuery学习中遇到的小细节进行了整理和总结 1.JQuery hide()和show()方法,分别对选中的元素进行隐藏和显示,语法:hide()和show分别有对应的 ...
- centos tomcat 安装
安装说明 安装环境:CentOS-6.3 安装方式:源码安装 软件:apache-tomcat-7.0.29.tar.gz 下载地址:http://tomcat.apache.org/downloa ...
- oc内容5大区
1.堆区(malloc):不需要手动管理内存,自动管理 2.栈区(stack):需要手动管理内存 3.静态区 4.常量区 5.方法区 load类方法:把类加载进内存的时候调用,只会调用一次 initi ...
- C语言:json库使用学习
Json基础 一.Json的概念 Json(Javascript Object Notation)全称为JavaScript对象表示法,是一种轻量级的数据交换格式,采用完全独立于语言的文本格式.JSO ...
- c# PictureBox 的图像上使用鼠标画矩形框
C# 中在图像上画框,通过鼠标来实现主要有四个消息响应函数MouseDown, MouseMove, MouseUp, Paint重绘函数实现.当鼠标键按下时开始画框,鼠标键抬起时画框结束. Poin ...
- DateTime & UTC 相互转化
public long ToUnixTime(DateTime date) { var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.U ...
- CODE[VS]-最小数和最大数-整数处理-天梯青铜
题目描述 Description 输入n个数,n<=100,找到其中最小的数和最大的数 输入描述 Input Description 第一行一个整数n 接下来一行n个整数,每个整数不超过231 ...