线程安全性与synchronized

线程安全:多线程访问某个类时,这个类始终都能表现出正确的行为,这个类就是线程安全的。

简单的说,就是多线程执行的结果与单线程执行的结果始终一致,不会因为多线程的执行时序不同而出现不同的结果

以下是一个线程不安全的程序:

当这段代码在单线程中执行时,会得出正确的答案,而在多线程环境中,则出现了执行结果完全靠运气,结果依赖于线程之间的执行时序,显然违背了线程安全的定义:多线程访问某个类时,这个类始终都能表现出正确的行为。

为什么会出现这样的结果?

虽然count++看上去很像是一个操作,实际在执行的时候是三个独立操作:

  1. 读取count的值。

  2. 将值+1。

  3. 写入count。

当上面这一个“读取-修改-写入”的操作没有使用同步机制保证这三步操作是一个不可分割原子操作,就会出现不同线程的这三步操作交替执行。

只需要加上一些线程协调机制便可将这三步操作作为一个原子操作,比如同步锁:

以上现象有一个术语来形容,叫竞态条件,即多线程访问同一资源时,如果对资源访问顺序敏感,执行结果依赖于线程的执行顺序,则为竞态条件。

Synchronized是java内置的锁,这是一种互斥锁,只能由一个线程进入被锁保护的代码,因此这个锁保护的代码块以原子方式执行,可以提供对象锁/类锁/安全发布全局变量的功能,

Synchronized的几种用法:

1.****对象锁:

2.****类锁:

使用锁时需要注意的地方:

  1. 当需要锁来协调线程对某个变量的访问时,所有访问这个变量的位置需要用同一个锁。

2.使用锁时要清楚代码块的代码是否需要执行很长时间,比如网络和IO操作,如果长时间持有锁,会造成线程竞争,等待的线程有两种等待策略:

a.忙锁:自旋等待锁释放,适合代码块执行时间很短的情况。

b.闲锁:将等待的线程挂起,锁释放后在合适的时机上下文切换,有一定内存同步代价。

jvm会对synchronized代码块进行不同程度的锁膨胀,偏向锁、轻量级锁、重量级锁,这个在后面的jvm系列博文会总结到。

当代码块执行的任务需要很长时间时尽量不要加锁。

同步代码块应尽可能短小,不需要同步的代码尽量移出,代码越短小,执行时间越短,线程竞争就越少,性能和吞吐量会更好,简单说就是快进快出

一些优化synchronized互斥锁性能的方法:

  1. 分段锁。

  2. 读写锁。

线程封闭

1. ad-hoc封闭:维护线程封闭性的职责完全由程序来承担。

例如代码中不做任何同步处理,只是把线程不安全的程序做成单线程程序,只有一个线程来执行了,自然就不会存在什么竞态条件、资源竞争,不推荐使用,建议用ThreadLocal。

在volatile变量上存在一种特殊的线程封闭。只要你能确保只有单个线程对共享的volatile变量执行写入操作,那么就可以安全地在这些共享的volatile变量上执行"读取—修改—写入"的操作。这种情况下相当于将修改操作封闭在单个线程中以防止发生竞态条件,并且volatile的可见性还确保其他的线程能看到最新的值。

  1. 栈封闭

简单说就是不用全局变量,用局部变量,方法内部声明的局部变量作用域是封闭在单个线程里的,不对其它线程共享,自然就不会出现竞态条件。



为什么栈封闭的局部变量能保证线程安全呢?后面更新的JVM系列会说明运行过程中的栈帧结构。

3. ThreadLocal

是一种更规范的维护线程封闭性的方式,使变量和持有变量的线程关联起来,每个变量都有一份自己的变量,相互隔离防止共享。

例如实现线程与用户信息的绑定:

不可变对象,不能修改,只读共享

不可变的成员变量不需要额外同步,天生线程安全,如果该成员变量是一个对象,则所有属性都需要声明为final保证不可变性。

如图static保证了jvm安全发布该变量,发布后对该类创建的所有线程都是可见的,final保证了发布后为只读,不可写。

当多线程程序存在线程安全问题时,选择解决方法的优先级应当如下:

1.能否做成无状态的不变对象。无状态是最安全的。

2.能否线程封闭。

3.采用何种同步技术。

线程安全与synchronized的更多相关文章

  1. Java线程同步(synchronized)——卖票问题

    卖票问题通常被用来举例说明线程同步问题,在Java中,采用关键字synchronized关键字来解决线程同步的问题. Java任意类型的对象都有一个标志位,该标志位具有0,1两种状态,其开始状态为1, ...

  2. 线程池 队列 synchronized

    线程池 BlockingQueue synchronized volatile 本章从线程池到阻塞队列BlockingQueue.从BlockingQueue到synchronized 和 volat ...

  3. Java线程锁,synchronized、wait、notify详解

    (原) JAVA多线程这一块有点绕,特别是对于锁,对锁机制理解不清的话,程序出现了问题也很难找到原因,在此记录一下线程的执行以及各种锁. 1.JAVA中,每个对象有且只有一把锁(lock),也叫监视器 ...

  4. 从线程池到synchronized关键字详解

    线程池 BlockingQueue synchronized volatile 前段时间看了一篇关于"一名3年工作经验的程序员应该具备的技能"文章,倍受打击.很多熟悉而又陌生的知识 ...

  5. java线程学习之synchronized关键字

    关键字synchronized的作用是实现线程间的同步.它的任务是对同步的代码加锁.一个代码块同时只能有同一个线程进行读和写操作,从而保证线程间是安全的. 线程安全的概念是:当多个线程访问某一个类(对 ...

  6. [多线程] 线程中的synchronized关键字锁

    为什么要用锁? 在多线程中,难免会出现在多个线程中对同一个对象的实例变量或者全局静态变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实 ...

  7. Java基础-多线程-③线程同步之synchronized

    使用线程同步解决多线程安全问题 上一篇 Java基础-多线程-②多线程的安全问题 中我们说到多线程可能引发的安全问题,原因在于多个线程共享了数据,且一个线程在操作(多为写操作)数据的过程中,另一个线程 ...

  8. java高并发系列 - 第10天:线程安全和synchronized关键字

    这是并发系列第10篇文章. 什么是线程安全? 当多个线程去访问同一个类(对象或方法)的时候,该类都能表现出正常的行为(与自己预想的结果一致),那我们就可以所这个类是线程安全的. 看一段代码: pack ...

  9. 线程安全之 synchronized 和 ReentrantLock

    线程安全之 synchronized 和 ReentrantLock + 面试题 前面我们介绍了很多关于多线程的内容,在多线程中有一个很重要的课题需要我们攻克,那就是线程安全问题.线程安全问题指的是在 ...

随机推荐

  1. 关于php中数据提交到当前页面action的问题

    关于php中数据提交到当前页面action的问题 2011-06-21 17:45杨超★杰伦 | 分类:PHP | 浏览695次 php中数据提交到当前页面,有人action=“<?php ec ...

  2. SQL server数据库的密码策略与登录失败锁定策略

    SQL server数据库本身没有密码复杂度策略设置,它是使用Windows操作系统的校验函数来校验账户密码的,所以查看SQL server数据库密码复杂度需要结合操作系统本地安全策略的密码策略来看. ...

  3. MyBatis——Mapped Statements collection does not contain value for XXX

    报错信息: Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql. ...

  4. 彻底理解JavaScript ES6中的import和export

    0.前言 前端工程,在最早的时候是没有模块的概念的.随着前端工程的发展,前端开发也越来越规范化,更像是软件工程了.那么随之而来的,为了解决工程化的问题,就引入了模块的概念.但是在早期,因为ecmasc ...

  5. 【Ubuntu】Ubuntu18.04通过重装系统成功安装显卡驱动

    0. 前言 前面用了一天的时间来解决Ubuntu安装显卡驱动出现的用户输入密码登录后出现的紫屏.循环登录的问题,过程可阅读“[Ubuntu]Ubuntu系统启动过程中,输入用户名与密码后登录一直卡在紫 ...

  6. return break 和continue在for循环中的不同作用

    平时自己经常在函数里见到return,在switch语句中使用break,而continue则用的不多. 其实这三者都能在for循环中发挥不同的作用,让代码更加灵活. 先说return return是 ...

  7. 突发!HashiCorp禁止在中国使用企业版VAULT软件

    目录 前言 HashiCorp公司介绍 HashiCorp旗下的软件 Provision Secure Connect Run 总结 前言 昨天HashiCorp突然发布一则消息,禁止在中国使用Vau ...

  8. ATT&CK红队评估实战靶场(一)

    靶机下载地址 http://vulnstack.qiyuanxuetang.net/vuln/detail/2/ 攻击拓扑如下 0x01环境搭建 配置两卡,仅主机模式192.168.52.0网段模拟内 ...

  9. jdk生成keystore、tomcat配置https

    一.首先利用jdk自带工具keytool生成keystore,命令如下:keytool -genkey -alias tomcat -keypass 123456 -keyalg RSA -keysi ...

  10. GNS3内网通过cloud与实际网络实现互连互通的实验(使用环回网口)

    一.背景: 在GNS3内构建一个测试网络,该测试网络的设备能够通过cloud访问外部网络设备和Internet网,外部网络也能直接访问GNS3内网的设备. 考虑通过cloud上的环回口连接GNS3内网 ...