zoukankan      html  css  js  c++  java
  • Java synchronized的使用

    需要明确的几个问题:

    • synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果 再细的分类,synchronized可作用于instance变量object reference(对象引用)、static函数和class literals(类名称字面常量)身上。
    • 无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。
    • 每个对象只有一个锁(lock)与之相关联。
    • 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

    synchronized关键字的作用域有二种:

    1. 某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线 程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的 synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;
    2. 某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。

    1、使用在方法上synchronized aMethod(){...}

      使用相同的 object

    public  class synchTest {
        private String a= "";
        private List<String> b= new ArrayList<>();
    
        // 方法一
        public  void job()  {
            System.out.println("job .....");
            synchronized (b){
                System.out.println("job 使用锁中 ....");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
            }
            System.out.println("job end.....");
        }
        // 方法二
        public synchronized void job2(){
            System.out.println("job2 .....");
            synchronized (b){
                System.out.println("job22 使用锁中 ...");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
            }
            System.out.println("job2 end.....");
        }
    
    
        public static void main(String[] args) {
            final synchTest rs = new synchTest();
            new Thread() {
                public void run() {
                    rs.job();
                }
            }.start();
            new Thread() {
                public void run() {
                    rs.job2();
                }
            }.start();
        }
    }
    
    结果:
    job .....
    job 使用锁中 ....
    job2 .....
    job end.....
    job22 使用锁中 ...
    job2 end.....
    View Code

         使用不同的object

    public  class synchTest {
        private String a= "";
        private List<String> b= new ArrayList<>();
    
        // 方法一
        public  void job()  {
            System.out.println("job .....");
            synchronized (a){
                System.out.println("job 使用锁中 ....");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
            }
            System.out.println("job end.....");
        }
        // 方法二
        public synchronized void job2(){
            System.out.println("job2 .....");
            synchronized (b){
                System.out.println("job22 使用锁中 ...");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
            }
            System.out.println("job2 end.....");
        }
    
    
        public static void main(String[] args) {
            final synchTest rs = new synchTest();
            new Thread() {
                public void run() {
                    rs.job();
                }
            }.start();
            new Thread() {
                public void run() {
                    rs.job2();
                }
            }.start();
        }
    }
    
    结果:
    job .....
    job 使用锁中 ....
    job2 .....
    job22 使用锁中 ...
    job end.....
    job2 end.....
    View Code

        使用this关键词 

    public  class synchTest {
        private String a= "";
        private List<String> b= new ArrayList<>();
    
        // 方法一
        public  void job()  {
            System.out.println("job .....");
            synchronized (this){
                System.out.println("job 使用锁中 ....");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
            }
            System.out.println("job end.....");
        }
        // 方法二
        public synchronized void job2(){
            System.out.println("job2 .....");
            synchronized (b){
                System.out.println("job22 使用锁中 ...");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
            }
            System.out.println("job2 end.....");
        }
    
    
        public static void main(String[] args) {
            final synchTest rs = new synchTest();
            new Thread() {
                public void run() {
                    rs.job();
                }
            }.start();
            new Thread() {
                public void run() {
                    rs.job2();
                }
            }.start();
        }
    }
    
    结果:
    job .....
    job 使用锁中 ....
    job end.....
    job2 .....
    job22 使用锁中 ...
    job2 end.....
    View Code

      结论:

    •   synchronized(Object) object相同的情况下,修饰的内容会同步,等上一个执行完才能执行下一个方法的内容
    •        synchronized(Object) object不相同的情况下,修饰内容不会同步,两个方法可以一起执行
    •         this这个比较特殊,如果先执行修饰this这个方法的内容,会同步,否则 不会同步(可以测试下)

    2、使用在方法内部 synchronized(Oject){...}

    public  class synchTest {
        // 方法一
        public synchronized   void job()  {
            System.out.println("job .....");
            System.out.println("job 使用锁中 ....");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println("job end.....");
        }
        // 方法二
        public synchronized void job2(){
            System.out.println("job2 .....");
            System.out.println("job22 使用锁中 ...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println("job2 end.....");
        }
    
        public static void main(String[] args) {
            final synchTest rs = new synchTest();
            new Thread() {
                public void run() {
                    rs.job();
                }
            }.start();
            new Thread() {
                public void run() {
                    rs.job2();
                }
            }.start();
        }
    }
    
    结果:
    job .....
    job 使用锁中 ....
    job end.....
    job2 .....
    job22 使用锁中 ...
    job2 end.....
    View Code

       结论:

    • 对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法,在对象内容所有的synchronized 的方法都会同步,必须等上一个方法执行完才能执行下一个方法

    2、使用在方法内部 synchronized(Oject){...}、synchronized aMethod(){...}混用

    public  class synchTest {
        public String a = "";
        // 方法一
        public void job()  {
            System.out.println("job .....");
            synchronized (a){
                System.out.println("job 使用锁中 ....");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
            }
            System.out.println("job end.....");
        }
        // 方法二
        public synchronized void job2(){
            System.out.println("job2 .....");
            System.out.println("job22 使用锁中 ...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println("job2 end.....");
        }
    
        public static void main(String[] args) {
            final synchTest rs = new synchTest();
            new Thread() {
                public void run() {
                    rs.job();
                }
            }.start();
            new Thread() {
                public void run() {
                    rs.job2();
                }
            }.start();
        }
    }
    结果:
    job .....
    job 使用锁中 ....
    job2 .....
    job22 使用锁中 ...
    job end.....
    job2 end.....
    View Code

       结论:

      对象实例内 synchronized aMethod(){} 与synchronized(Object)  不会相互同步

  • 相关阅读:
    BZOJ3510 首都
    洛谷U19464 山村游历(Wander)(LCT)
    [BZOJ4530][Bjoi2014]大融合(LCT)
    POJ 3522 最小差值生成树(LCT)
    AHOI2005航线规划 bzoj1969(LCT缩点)
    P3950 部落冲突
    BZOJ2243 [SDOI2011]染色(LCT)
    P1501 [国家集训队]Tree II
    性能优化之优化加载资源
    Hexo next主题安装algolia
  • 原文地址:https://www.cnblogs.com/lemon-flm/p/14346033.html
Copyright © 2011-2022 走看看