Java 中的 synchronized 关键字

一. 为什么要使用 synchronized

  在并发编程中存在线程安全问题,主要原因有:

  1. 存在共享数据

  2.多线程共同操作共享数据。

  关键字 synchronized 可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时 synchronized 可以保证一个线程的变化可见(可见性),即可以代替volatile。

二. 实现原理

  synchronized 可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性。

三. 应用方式

  synchronized 是Java中的关键字,是一种同步锁。它修饰的对象有以下几种: 

  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象; 

    1.1 当两个并发线程(thread1 和 thread2)访问同一个对象(syncThread)中的 synchronized 代码块时,在同一时刻只能有一个线程得到执行,另一个线程受阻塞,必须等待当前线程执行完这个代码块以后才能执行该代码块。

    thread1 和 thread2 是互斥的,因为在执行 synchronized 代码块时会锁定当前的对象,只有执行完该代码块才能释放该对象锁,下一个线程才能执行并锁定该对象。

    1.2 当一个线程访问对象的一个 synchronized(this) 同步代码块时,另一个线程仍然可以访问该对象中的非 synchronized(this) 同步代码块。 

  2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象; 

    synchronized 修饰一个方法很简单,就是在方法的前面加synchronized,public synchronized void method(){};

    synchronized 修饰方法和修饰代码块类似,只是作用范围不一样,修饰代码块是大括号括起来的范围,而修饰方法范围是整个函数。

    注意:

    2.1 synchronized 关键字不能继承。 
      虽然可以使用 synchronized 来定义方法,但 synchronized 并不属于方法定义的一部分,因此,synchronized 关键字不能被继承。

      如果在父类中的某个方法使用了 synchronized 关键字,而在子类中覆盖了这个方法,在子类中的这个方法默认情况下并不是同步的,而必须显式地在子类的这个方法中加上 synchronized 关键字才可以。

      当然,还可以在子类方法中调用父类中相应的方法,这样虽然子类中的方法不是同步的,但子类调用了父类的同步方法,因此,子类的方法也就相当于同步了。

    2.2 在定义接口方法不能使用 synchronized 关键字。

    2.3 构造方法不能使用 synchronized 关键字,但可以使用 synchronized 代码块来进行同步。

  3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象; 

  4. 修改一个,其作用的范围是 synchronized 后面括号括起来的部分,作用的对象是这个类的所有对象

 

四. 作用

  synchronized 是Java中解决并发问题的一种最常用最简单的方法 ,他可以确保线程互斥的访问同步代码

  

posted @ 2021-03-16 12:28  zjcfrancis  阅读(163)  评论(0编辑  收藏  举报