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)  不会相互同步

原文地址:https://www.cnblogs.com/lemon-flm/p/14346033.html