java多线程编程之Synchronized关键字详解

 更新时间:2016年05月14日 18:23:54   作者:hapjin  
这篇文章主要为大家详细介绍了java多线程编程之Synchronized关键字,感兴趣的朋友可以参考一下

本文介绍JAVA多线程中的synchronized关键字作为对象锁的一些知识点。

所谓对象锁,就是就是synchronized 给某个对象 加锁。关于 对象锁 可参考:这篇文章

 一、分析

synchronized可以修饰实例方法,如下形式:

public class MyObject {
  synchronized public void methodA() {
    //do something....
  }

这里,synchronized 关键字锁住的是当前对象。这也是称为对象锁的原因。

为啥锁住当前对象?因为 methodA()是个实例方法,要想执行methodA(),需要以 对象.方法() 的形式进行调用(obj.methodA(),obj是MyObject类的一个对象,synchronized就是把obj这个对象加锁了)。

上面代码也可写成这样:

public class MyObject {

  public void methodA() {
    synchronized(this){
      //do something....
    }
  }
 

二、特点

使用synchronized关键字同步一个明显的特点是:MyObject类中定义有多个synchronized修饰的实例方法时,若多个线程拥有同一个MyObject类的对象,则这些方法只能以同步的方式执行。即,执行完一个synchronized修饰的方法后,才能执行另一个synchronized修饰的方法。

如下:

public class MyObject {

  synchronized public void methodA() {
    //do something....
  }

  synchronized public void methodB() {
    //do some other thing
  }
}

MyObject类中有两个synchronized修饰的方法。

public class ThreadA extends Thread {

  private MyObject object;
//省略构造方法
  @Override
  public void run() {
    super.run();
    object.methodA();
  }
}

线程A执行methodA()

public class ThreadB extends Thread {

  private MyObject object;
//省略构造方法
  @Override
  public void run() {
    super.run();
    object.methodB();
  }
}

线程B执行methodB()

public class Run {
  public static void main(String[] args) {
    MyObject object = new MyObject();

    //线程A与线程B 持有的是同一个对象:object
    ThreadA a = new ThreadA(object);
    ThreadB b = new ThreadB(object);
    a.start();
    b.start();
  }
}

由于线程A和线程B持有同一个MyObject类的对象object,尽管这两个线程需要调用不同的方法,但是必须是同步的,比如:线程B需要等待线程A执行完了methodA()方法之后,它才能执行methodB()方法。

 三、结论

从上可以看出,本文中讲述的 synchronized 锁的范围是整个对象。如果一个类中有多个synchronized修饰的同步方法,且多个线程持有该类的同一个对象(该类的相同的对象),尽管它们调用不同的方法,各个方法的执行也是同步的。

如果各个同步的方法之间没有共享变量,或者说各个方法之间没有联系,但也只能同步执行,这会影响效率。

四、应用--使用synchronized避免 因数据不一致性而导致读脏数据的情况

如下示例:

public class MyObject {

  private String userName = "b";
  private String passWord = "bb";
  
  synchronized public void methodA(String userName, String passWord) {
    this.userName = userName;
    try{
      Thread.sleep(5000);
    }catch(InterruptedException e){
      
    }
    this.passWord = passWord;
  }

  synchronized public void methodB() {
    System.out.println("userName" + userName + ": " + "passWord" + passWord);
  }
}

methodA()负责更改用户名和密码。在现实中,一个用户名对应着一个密码。

methodB()负责读取用户名和密码。

如果methodB()没有用synchronized 修饰,线程A在调用methodA()执行到第7行,更改了用户名,因某种原因(比如在第9行睡眠了)放弃了CPU。

此时,如果线程B去执行methodB(),那么读取到的用户名是线程A更改了的用户名("a"),但是密码却是原来的密码("bb")。因为,线程A睡眠了,还没有来得及更改密码。

但是,如果methodB()用synchronized修饰,那么线程B只能等待线程A执行完毕之后(即改了用户名,也改了密码),才能执行methodB读取用户名和密码。因此,就避免了数据的不一致性而导致的脏读问题。

以上就是本文的全部内容,希望对大家学习java程序设计有所帮助。

相关文章

  • SpringBoot登录判断过程代码实例

    SpringBoot登录判断过程代码实例

    这篇文章主要介绍了SpringBoot登录判断代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • JavaWeb中转发与重定向的区别小结

    JavaWeb中转发与重定向的区别小结

    转发和重定向是JavaWeb中常用的两种页面跳转方式,它们在实现上有一些区别,本文主要介绍了JavaWeb中转发与重定向的区别小结,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • spring MVC实现简单登录功能

    spring MVC实现简单登录功能

    这篇文章主要为大家详细介绍了spring MVC实现简单登录功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09
  • Mybatis之#{}与${}的区别使用详解

    Mybatis之#{}与${}的区别使用详解

    这篇文章主要介绍了Mybatis之#{}与${}的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • Springboot+Hutool自定义注解实现数据脱敏

    Springboot+Hutool自定义注解实现数据脱敏

    我们在项目中会处理敏感数据时,通常需要对这些数据进行脱敏,本文主要使用了Springboot整合Hutool来自定义注解实现数据脱敏,感兴趣的可以理解下
    2023-10-10
  • IDEA配置SpringBoot热启动,以及热启动失效问题

    IDEA配置SpringBoot热启动,以及热启动失效问题

    这篇文章主要介绍了IDEA配置SpringBoot热启动,以及热启动失效问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • SpringBoot Admin 如何实现Actuator端点可视化监控

    SpringBoot Admin 如何实现Actuator端点可视化监控

    这篇文章主要介绍了SpringBoot Admin 如何实现Actuator端点可视化监控,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • java 实现微信服务器下载图片到自己服务器

    java 实现微信服务器下载图片到自己服务器

    这篇文章主要介绍了 java 实现微信服务器下载图片到自己服务器的相关资料,需要的朋友可以参考下
    2017-05-05
  • 浅谈java 中equals和==的区别

    浅谈java 中equals和==的区别

    这篇文章主要介绍了java 中equals和==的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Java变量的初始化及静态方法的实现

    Java变量的初始化及静态方法的实现

    这篇文章主要介绍了Java变量的初始化及静态方法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10

最新评论