码迷,mamicode.com
首页 > 编程语言 > 详细

Java多线程-synchronized(非this对象)

时间:2020-03-15 19:04:26      阅读:82      评论:0      收藏:0      [点我收藏+]

标签:main   应用   效果   except   代码块   public   开始   inter   exce   

3个结论

synchronized(非this对象 x) 是将 x 对象本身作为“对象监视器”,因此有如下三个结论:

1)当多个线程同时执行 synchronized(x){}同步代码块时呈同步效果

2)当其他线程执行 x 对象中 synchronized 同步方法时呈同步效果

3)当其他线程执行 x 对象方法里的 synchronized(this) 代码块时也呈现同步效果。

 

静态同步方法 与 synchronized(class)代码块

关键字 synchronized 还可以应用在 static 静态方法上,如果这样写,则是对当前“类对象”进行持锁

注意区别:

  synchronized 作用在非 static 方法上时,是“对象锁”,作用到 static 方法上时,是“Class锁”

示例:

public class SyncNotThis {
    public static void main(String[] args) {
        Service service = new Service();

        Thread t1 = new Thread(() -> {
            Service.printA();
        });
        Thread t2 = new Thread(() -> {
            Service.printB();
        });
        Thread t3 = new Thread(() -> {
            service.printC();
        });
        t1.start();
        t2.start();
        t3.start();
    }

    static class Service {
        /**
         * 静态方法 A
         */
        synchronized public static void printA() {
            try {
                System.out.println("线程名称为:" + Thread.currentThread().getName() + "开始执行 A 方法");
                Thread.sleep(1000);
                System.out.println("线程名称为:" + Thread.currentThread().getName() + "结束执行 A 方法");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        /**
         * 静态方法B
         */
        synchronized public static void printB() {
            try {
                System.out.println("线程名称为:" + Thread.currentThread().getName() + "开始执行 B 方法");
                Thread.sleep(1000);
                System.out.println("线程名称为:" + Thread.currentThread().getName() + "结束执行 B 方法");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        /**
         * 非静态方法C
         */
        synchronized public void printC() {
            try {
                System.out.println("线程名称为:" + Thread.currentThread().getName() + "开始执行 C 方法");
                Thread.sleep(500);
                System.out.println("线程名称为:" + Thread.currentThread().getName() + "结束执行 C 方法");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果如图:

技术图片

 

 可以发现 方法 A、B的运行呈现同步效果,方法C与 A、B呈现异步效果,异步的原因是方法 C与 方法 A、B持有的是不同的锁

 

synchronized(String对象)的特殊情况

因为JVM中String常量池的存在,会导致 synchronized锁到同一对象

例:

public class SyncString {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            String aa = "AA";
            print(aa);
        });
        Thread t2 = new Thread(() -> {
            String aa = "AA";
            print(aa);
        });
        t1.start();
        t2.start();
    }

    public static void print(String stringParam) {
        synchronized (stringParam) {
            try {
                System.out.println(Thread.currentThread().getName() + "begin");
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName() + "end");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果如下:

技术图片

 

 因为String 常量池导致了锁的是同一 String 对象,所以两个线程是同步执行的

Java多线程-synchronized(非this对象)

标签:main   应用   效果   except   代码块   public   开始   inter   exce   

原文地址:https://www.cnblogs.com/lkc9/p/12499134.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!