乌市泽哥 发表于 2024-8-1 23:01:00

Java线程安全之同步方法

同步方法

使用synchronized修饰的方法,就叫做同步方法,其固定格式如下:
public synchronized 返回值类型 同步方法() {
        可能会产生线程安全问题的代码
}
留意事项:


[*]同步方法可以是平凡成员方法,也可以是static静态方法
[*]平凡成员同步方法,默认锁对象为this,即当火线法的调用对象
[*]static静态同步方法,默认锁对象是当前类的字节码对象(一个类有且只有一个)
   类的字节码对象:类名.class,固定用法(当前记取即可,后续反射章节会学习)
案例1:平凡同步方法
​ 创建子线程1,调用100次平凡方法print1(逐字输出 “好好学习”)
​ 创建子线程2,调用100次平凡方法print2(逐字输出 “天天向上”)
​ 要求,两个子线程在执行方法的过程中,不会被另一个线程打断。
class Printer {
        //普通同步方法: 锁对象默认为this
        public synchronized void print1() {
                System.out.print("天");
                System.out.print("天");
                System.out.print("向");
                System.out.print("上");
                System.out.println();
        }
       
        public void print2() {       
      //同步代码块,也使用this作为锁对象
      //测试时,可以注释同步代码块,或使用其他锁对象,然后观察程序运行效果
                //synchronized (Printer.class) {
      synchronized (this) {
                        System.out.print("努");
                        System.out.print("力");
                        System.out.print("学");
                        System.out.print("习");
                        System.out.println();
                }
        }
}

public class Test16_Funtion {
        public static void main(String[] args) {
                //准备一个对象
                final Printer p = new Printer();
               
                //创建子线程1,输出100次 "好好学习"
                Thread th1 = new Thread() {
                        @Override
                        public void run() {
                                for(int i = 0; i < 100; i++)
                                        p.print1();
                        }
                };
               
                //创建子线程2,输出100次 "天天向上"
                Thread th2 = new Thread() {
                        @Override
                        public void run() {
                                for(int i = 0; i < 100; i++)
                                        p.print2();
                        }
                };
               
                th1.start();
                th2.start();
        }
}
测试结果:


[*]print2方法不使用同步代码块,或不使用this作为锁对象,会出现输出杂乱的情况,线程没有实现同步(上锁失败)
https://i-blog.csdnimg.cn/direct/115defb5c7c549ab82e3330479ad895e.png


[*]print2方法使用同步代码块,且用this作为锁对象,成功实现线程同步
https://i-blog.csdnimg.cn/direct/313732fe72df42acad24f7575bfd3f69.png
案例2:静态同步方法
​ 将上述案例中的平凡同步方法,修改为静态同步方法,实现原有功能。
class Printer {
    // ...省略print1() print2()
   
        //static静态同步方法: 锁对象默认为当前类字节码对象
        public static synchronized void print3() {
                System.out.print("天");
                System.out.print("天");
                System.out.print("向");
                System.out.print("上");
                System.out.println();
        }
       
        public void print4() {       
      //同步代码块,使用当前类字节码对象作为锁对象
      
      //注释掉同步代码块,运行测试,观察效果
      //不使用当前类字节码对象作为锁对象,运行测试,观察效果
      //synchronized (this) {
                synchronized (Printer.class) {
                        System.out.print("努");
                        System.out.print("力");
                        System.out.print("学");
                        System.out.print("习");
                        System.out.println();
                }
        }
}

public class Test16_Funtion {
        public static void main(String[] args) {
                //准备一个对象
                final Printer p = new Printer();
               
                //创建子线程1,输出100次 "好好学习"
                Thread th1 = new Thread() {
                        @Override
                        public void run() {
                                for(int i = 0; i < 100; i++)
                                        Printer.print3();
                        }
                };
               
                //创建子线程2,输出100次 "天天向上"
                Thread th2 = new Thread() {
                        @Override
                        public void run() {
                                for(int i = 0; i < 100; i++)
                                        p.print4();
                        }
                };
               
                th1.start();
                th2.start();
        }
}
运行测试:
​ 按照print4方法中形貌进行测试,验证结论:
   static静态同步方法: 锁对象默认为当前类字节码对象(类名.class)
线程状态图为:
https://i-blog.csdnimg.cn/direct/ce762376f91748b09fa144907905860c.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Java线程安全之同步方法