脏读

一个常见的概念。在多线程中,难免会出现在多个线程中对同一个对象的实例变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实是被更改过的。

按照正常来看应该打印"a num = 100"和"b num = 200"才对,现在却打印了"b num = 200"和"a num = 200",这就是线程安全问题。我们可以想一下是怎么会有线程安全的问题的:

1、mt0先运行,给num赋值100,然后打印出"a set over!",开始睡觉

2、mt0在睡觉的时候,mt1运行了,给num赋值200,然后打印出"b set over!",然后打印"b num = 200"

3、mt1睡完觉了,由于mt0的num和mt1的num是同一个num,所以mt1把num改为了200了,mt0也没办法,对于它来说,num只能是100,mt0继续运行代码,打印出"a num = 200"

分析了产生问题的原因,解决就很简单了,给addNum(String userName)方法加同步即可:

打印结果的方式变了,打印的顺序是交叉的,这又是为什么呢?

这里有一个重要的概念。关键字synchronized取得的锁都是对象锁,而不是把一段代码或方法(函数)当作锁,哪个线程先执行带synchronized关键字的方法,哪个线程就持有该方法所属对象的锁,其他线程都只能呈等待状态。但是这有个前提:既然锁叫做对象锁,那么势必和对象相关,所以多个线程访问的必须是同一个对象

如果多个线程访问的是多个对象,那么Java虚拟机就会创建多个锁,就像上面的例子一样,创建了两个ThreadDomain13对象,就产生了2个锁。既然两个线程持有的是不同的锁,自然不会受到"等待释放锁"这一行为的制约,可以分别运行addNum(String userName)中的代码。

synchronized方法与锁对象

从结果看到,第一个线程调用了实体类的methodA()方法,第二个线程完全可以调用实体类的methodB()方法。但是我们把methodB()方法改为同步就不一样了,就不列修改之后的代码了,看一下运行结果:

从这个例子我们得出两个重要结论:

1、A线程持有Object对象的Lock锁,B线程可以以异步方式调用Object对象中的非synchronized类型的方法

2、A线程持有Object对象的Lock锁,B线程如果在这时调用Object对象中的synchronized类型的方法则需要等待,也就是同步

synchronized锁重入

关键字synchronized拥有锁重入的功能。所谓锁重入的意思就是:当一个线程得到一个对象锁后,再次请求此对象锁时时可以再次得到该对象的锁。看一个例子:

看到可以直接调用ThreadDomain16中的打印语句,这证明了对象可以再次获取自己的内部锁。这种锁重入的机制,也支持在父子类继承的环境中

异常自动释放锁

最后一个知识点是异常。当一个线程执行的代码出现异常时,其所持有的锁会自动释放。模拟的是把一个long型数作为除数,从MAX_VALUE开始递减,直至减为0,从而产生ArithmeticException。看一下例子:

因为打印结果是静态的,所以不是很明显。在l--前一句加上Thread.sleep(1)结论会更明显,第一句打出来之后,整个程序都停住了,直到Thread-0抛出异常后,Thread-1才可以运行,这也证明了我们的结论。

Java多线程4:synchronized锁机制相关推荐

  1. Java 多线程 不使用锁机制 实现交替打印数字和字母

    Java 多线程 不使用锁机制 实现交替打印数字和字母 这是一道经典的面试题,使用两个线程去交替打印数字和字母,输出1A2B3C4D5E6F7G-这样的效果,看了网上很多的文章,基本都是使用Condi ...

  2. JUC多线程:synchronized锁机制原理 与 Lock锁机制

    前言: 线程安全是并发编程中的重要关注点,造成线程安全问题的主要原因有两点,一是存在共享数据(也称临界资源),二是存在多条线程共同操作共享数据.因此为了解决这个问题,我们可能需要这样一个方案,当存在多 ...

  3. Java多线程之线程同步机制(锁,线程池等等)

    Java多线程之线程同步机制 一.概念 1.并发 2.起因 3.缺点 二.三大不安全案例 1.样例一(模拟买票场景) 2.样例二(模拟取钱场景) 3.样例三(模拟集合) 三.同步方法及同步块 1.同步 ...

  4. Java多线程系列---“JUC锁”01之 框架

    本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下: 01. Java多线程系列--"JUC锁"01之 框架 02. Java多线程系列--"JUC锁 ...

  5. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对"公平锁"的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括: 基本概念 ReentrantLock数据结构 参考代码 获取公平锁(基于JDK1.7.0 ...

  6. Java多线程:synchronized | Volatile 和Lock和ReadWriteLock多方位剖析(一)

    前言 本文站在多线程初中级学习者的角度,较为全面系统的带你一起了解多线程与锁相关的知识点.带你一起解开与锁相关的各种概念.用法.利弊等.比如:synchronized.Volatile.Lock.Re ...

  7. Java并发编程之锁机制之LockSupport工具

    关于文章涉及到的jdk源码,这里把最新的jdk源码分享给大家----->jdk源码 前言 在上篇文章<Java并发编程之锁机制之AQS(AbstractQueuedSynchronizer ...

  8. Java基础-Java中常用的锁机制与使用

    Java基础-Java中常用的锁机制与使用 锁lock或互斥mutex是一种同步机制,主要用于在存在多线程的环境中强制对资源进行访问限制.锁的主要作用为强制实施互斥排他以及并发控制策略.锁一般需要硬件 ...

  9. Java 并发编程解析 | 如何正确理解Java领域中的锁机制,我们一般需要掌握哪些理论知识?

    苍穹之边,浩瀚之挚,眰恦之美: 悟心悟性,善始善终,惟善惟道! -- 朝槿<朝槿兮年说> 写在开头 提起Java领域中的锁,是否有种"道不尽红尘奢恋,诉不完人间恩怨"的 ...

  10. Java:java学习笔记之锁机制的简单理解和使用

    锁机制的简单理解和使用 锁机制 1.背景 2.定义 3.锁的种类 4.乐观锁 VS 悲观锁 4.1.悲观锁 4.2.乐观锁 4.3.举例说明 4.4.CAS算法 4.4.1.CAS使用 4.4.2.C ...

最新文章

  1. 微信小程序与H5相互跳转和传递数据
  2. 单行文本溢出显示省略号,单行文本溢出显示省略号
  3. JZOJ 3.10 1542——跑步(树状数组+模拟+排序/归并排序)
  4. opengl源码 实现无缝切换图片过场_手把手讲解 Android hook技术实现一键换肤
  5. OpenCASCADE绘制测试线束:数据交换命令之一般命令
  6. java分页模板_java 分页模型的模板
  7. kafka解决了什么问题?
  8. 【转】彻底理解cookie,session,token
  9. java Map统计字符串中元素的数量
  10. 微信WeixinJSBridge API 屏蔽右上角分享等常用方法
  11. css基础知识汇总3
  12. kafka安装java,Linux下Kafka单机安装配置方法(图文)
  13. svnadmin dump导入导出命令
  14. Android ADB 环境变量配置
  15. MII/MDIO接口详解
  16. 计算机键盘的删除键,电脑删除键在哪 删除的快捷键是什么
  17. 三月写给沉默王二的一封道歉信
  18. 软著申请技巧及注意事项
  19. 11_04_第六阶段:大前端进阶||07-Vue详解||P6:Vue绑定事件【观看狂神随笔】
  20. (每日一练C++)寻找孪生素数

热门文章

  1. SQL Server代理的阶梯 - 第2级:作业步骤和子系列
  2. 安卓UI测试(基于android studio环境 espresso框架)
  3. apache 设置禁止访问某些文件或目录
  4. pom.xml的配置详解
  5. Error: could not open `C:\Java\jre7\lib\i386\jvm.cfg
  6. HDU-水饺基情 二维树状数组
  7. 2. with check option能起什么作用?_面部毛孔粗大,有什么拯救的方法吗?
  8. Mybatis之SqlSession简析
  9. docker为什么比虚拟机快
  10. html css外接修改无效,HTML外部引用CSS文件为什么会不生效