一,介绍

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

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

二,分析

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

1 public class MyObject {
2
3 synchronized public void methodA() {
4 //do something....
5 }

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

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

上面代码也可写成这样:

1 public class MyObject {
2
3 public void methodA() {
4 synchronized(this){
5 //do something....
6 }
7 }

三,特点

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

如下:

 1 public class MyObject {
2
3 synchronized public void methodA() {
4 //do something....
5 }
6
7 synchronized public void methodB() {
8 //do some other thing
9 }
10 }

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

 1 public class ThreadA extends Thread {
2
3 private MyObject object;
4 //省略构造方法
5 @Override
6 public void run() {
7 super.run();
8 object.methodA();
9 }
10 }

线程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避免 因数据不一致性而导致读脏数据的情况

如下示例:

 1 public class MyObject {
2
3 private String userName = "b";
4 private String passWord = "bb";
5
6 synchronized public void methodA(String userName, String passWord) {
7 this.userName = userName;
8 try{
9 Thread.sleep(5000);
10 }catch(InterruptedException e){
11
12 }
13 this.passWord = passWord;
14 }
15
16 synchronized public void methodB() {
17 System.out.println("userName" + userName + ": " + "passWord" + passWord);
18 }
19 }

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

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

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

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

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

JAVA多线程之Synchronized关键字--对象锁的特点的更多相关文章

  1. Java多线程之synchronized(四)

    前面几章都是在说synchronized用于对象锁,无论是修饰方法也好修饰代码块也好,然而关键字synchronized还可以应用到static静态方法上,如果这样写,那就是对当前的*.java文件所 ...

  2. Java多线程之synchronized及其优化

    Synchronized和同步阻塞synchronized是jvm提供的同步和锁机制,与之对应的是jdk层面的J.U.C提供的基于AbstractQueuedSynchronizer的并发组件.syn ...

  3. Java并发编程之synchronized关键字

    整理一下synchronized关键字相关的知识点. 在多线程并发编程中synchronized扮演着相当重要的角色,synchronized关键字是用来控制线程同步的,可以保证在同一个时刻,只有一个 ...

  4. Java多线程之synchronized详解

    目录 synchronized简介 同步的原理 对象头与锁的实现 锁的优化与升级 Monitor Record 锁的对比 synchronized简介 synchronized关键字,一般称之为&qu ...

  5. Java多线程之synchronized(二)

    为了解决“非线程安全”带来的问题,上一节中使用的办法是用关键字synchronized修饰多个线程可能同时访问到的方法,但是这样写是存在一定的弊端的,比如线程A调用一个用synchronized修饰的 ...

  6. Java多线程之synchronized(一)

    在上节中已经说过了“非线程安全”是如何出现的,链接如下:http://www.cnblogs.com/chentong/p/5650137.html,那么怎么解决“非线程安全”问题呢,只需要在两个线程 ...

  7. JAVA多线程之Synchronized、wait、notify实例讲解

    一.Synchronized synchronized中文解释是同步,那么什么是同步呢,解释就是程序中用于控制不同线程间操作发生相对顺序的机制,通俗来讲就是2点,第一要有多线程,第二当多个线程同时竞争 ...

  8. JAVA多线程之synchronized和volatile实例讲解

    在多线程中,提到线程安全.线程同步,我们经常会想到两个关键字:volatile和synchronized,那么这两者有什么区别呢? 1. volatile修饰的变量具有可见性 volatile是变量修 ...

  9. java多线程之synchronized(线程同步)

    一.线程同步,主要应用synchronized关键字: public class TraditionalThreadSynchorinzed { public static void main(Str ...

随机推荐

  1. 如何将HLS延时缩短至4秒,HLS+技术详解

    在直播应用中,RTMP 和 HLS 是两种较为成熟且广泛应用的流媒体协议,基本上可以覆盖所有客户端.RTMP 是互联网 TCP/IP 五层体系结构中应用层的协议,主要优势就是实时性高,基本可将直播延时 ...

  2. head first python helloword

    如何使用python 打出hello word 在python shell 键入print 'hello word'( python 2) or  print ("hello word&qu ...

  3. 【转载】The Elements of Programming Style之代码风格金科玉律

    原始日期: 2017-02-06 16:20 <The Elements of Programming Style >是一本很古老的书.尽管 Fortran 我们不太使用,尽管新奇的语言层 ...

  4. 在PHP中连接数据库的八大步骤

                                                                                   连接数据库的八大步骤  Step1:链接数 ...

  5. 如何成为一名JAVAEE软件工程师?(前言)

    笔者将会整理出一整套成为一个JAVAEE工程师的学习路线和资料.欢迎同行和网友们订阅或指正.不定期更新.         笔者在软件工作做了7年java开发,开发过ERP,CRM等应用系统并担任过项目 ...

  6. linux下如何解压和压缩文件

    1.*.tar 用 tar –xvf 解压 2.*.gz 用 gzip -d或者gunzip 解压 3.*.tar.gz和*.tgz 用 tar –xzf 解压 4.*.bz2 用 bzip2 -d或 ...

  7. abelkhan服务器框架

    abelkhan是一个开源的游戏服务器框架.目标是提供一个稳定.高效.可扩展的服务器框架. github:https://github.com/qianqians/abelkhan 论坛:http:/ ...

  8. openssl req(生成证书请求和自建CA)

    伪命令req大致有3个功能:生成证书请求文件.验证证书请求文件和创建根CA.由于openssl req命令选项较多,所以先各举几个例子,再集中给出openssl req的选项说明.若已熟悉openss ...

  9. EXT 基础环境搭建

    EXT 基础环境搭建使用 Sencha CMD 下载地址 https://www.sencha.com/products/extjs/cmd-download/ Sencha CMD 常用命令 API ...

  10. SQLite的总结与在C#的使用

    这几天接触了一下SQLite,算是有点收获吧,因此总结一下. SQLite简介: SQLite是用C语言编写的数据库引擎,可以运行在Linux.Windows.Mac平台上. SQLite安装简单,下 ...