深入理解Java并发synchronized同步化的代码块不是this对象时的操作

一.明确一点synchronized同步的是对象不是方法也不是代码块 我有关synchronized同步的是对象讨论的博客在这里:https://www.cnblogs.com/SAM-CJM/p/9798263.html 只要明确了synchronized同步的是对象那么,底下的问题就好解决了。 二.问题的导入 首先我有一个班级,班级中有学生。那么我们可以这样来模拟这个问题,代码如下: 复制代码 import java.util.ArrayList; public class Class { //班级类 ArrayList students; public Class(ArrayList students){ this.students=students; } } //学生类 class Student{ private String name; private int ID; public Student(String name,int ID){ this.ID=ID; this.name=name; } } 复制代码 然后我们有一个班级事务处理类,来处理事务,这个类继承了Thread类代码入下: 复制代码 import java.util.ArrayList; import java.util.Arrays; public class ClassText extends Thread{//班级事务处理类 Class class1;//待处理事务的班级 //构造器 public ClassText(Class class1){ this.class1=class1; } @Override//没有同步run方法 public void run(){ super.run(); addStudent(new Student("张三",15)); } //添加学生,没有同步该方法 public void addStudent(Student student){ System.out.println("添加前现在有"+class1.students.size()+"个学生"); class1.students.add(student); System.out.println("添加后现在有"+class1.students.size()+"个学生"); } public static void main(String[] args) { Class c=new Class(new ArrayList<>(Arrays.asList(new Student("李四",20),new Student("赵牛",20)))); ClassText ct1=new ClassText(c); ClassText ct2=new ClassText(c); ct1.start(); ct2.start(); } } 复制代码 显然上面的代码是错误的,他没同步两个线程,那么我们看看结果是什么样子的: 果然出现了线程不安全的情况。 那么,我们马上同步化我们的addStudent方法或者是run方法,代码如下: 这里同步addStudent方法 复制代码 //添加学生,同步化该方法 public synchronized void addStudent(Student student){ System.out.println("添加前现在有"+class1.students.size()+"个学生"); class1.students.add(student); System.out.println("添加后现在有"+class1.students.size()+"个学生"); } 复制代码 结果如下: 还是不同步的。 那么这到底是为什么呢? 三.解决方法 其实我们无论在ClassText类里面的哪个方法加synchronized使其同步化都是没有用的,因为你同步化的是你的ClassText对象,而我们要同步的是处理的是在ClassText类中组合Class对象,因为我们是对他的进行共享资源的操作,那么问题来了,怎么对不是本身对象进行一个同步化操作呢?还是使用synchronized同步代码块只不过同步对象不再是this了而是共享数据处理的对象,修改代码如下: 复制代码 //添加学生 public void addStudent(Student student){ //同步化修改共享数据的对象 synchronized (class1){ System.out.println("添加前现在有"+class1.students.size()+"个学生"); class1.students.add(student); System.out.println("添加后现在有"+class1.students.size()+"个学生"); } } 复制代码 结果如下:没毛病了! 当然你把添加学生的添加函数放到Class类中,同步改方法也是没问题的 所以还是那一条,同步化的对象,是需要同步化的对象。https://www.cnblogs.com/SAM-CJM/p/9810385.html
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信