关于线程安全的话题,足可以使用一本书来讲解这些东西。<Java Concurrency in Practice> 就是讲解这些的,在这里

主要还是分析JVM中关于线程安全这块的内容。

1.线程安全是什么?

线程安全,有经验的开发人员都听过这个名词,但是能否给到一个准确的定义,很难。

在 Java Concurrency in Practice里面定义是:

当多个线程访问一个对象时,如果不用考虑这些线程在运行时的环境下的调度和交替执行,

也不需要进行额外的同步,或者调用其他协作,这个情况下,线程就是安全的。

java中的线程安全可以定义5个级别:

1)不可改变。

也就是final修饰的词。

public class ThreadSafeType {

    class ThreadContext{
public int id = -1;
} public void doSomeThingBackground(ThreadContext context)
{
new Thread(){
@Override
public void run(){
context.id++;
}
}.start();
}
}

上面标红的,会再android studio里面提示错误:

从内部类中访问本地变量context; 需要被声明为最终类型。

也就是说在

public void doSomeThingBackground(final ThreadContext context)

要改成上面的类型,这就是线程安全的考虑。

2)绝对安全

绝对安全其实很难描述,比如Vector是安全的。但是在多线程的情况下,它也是不安全的。

3)相对安全

相对安全其实就是我们一般意义上的线程安全。

它需要保证对这个对象的单独操作是安全的。但是对于特定的顺序,需要一些方法保证线程安全。

4)线程兼容

这就是我们常见的情况,需要使用synchronized等手段来保证线程安全。

5)线程对立

比较极端的情况,就是无论怎么加锁,代码无法并发运行。一种情况就是死锁。

2.如何实现线程安全

1)互斥同步

保持共享数据在同一时刻只被一个线程使用。

互斥是手段,同步是目的。

在java中最常见的就是synchronized方法。

synchronized标记的代码,会生成monitorenter & monitorexit  2段代码。

这是java编译器自动生成的,不会有遗漏。使用其他锁,lock & unlock成对出现,但是

开发者有时候会容易疏忽这个操作,尤其在catch代码里面忘记调用unlock,将是一个隐患。

java.util.concurrent 下面有不少同步的方法。ReentrantLock也是一个可以的方法,在1.5以前,性能

远由于synchronized。但是在1.6, java还是把synchronized做了很大的提升。原因就是synchronized使用的

代码已经远远大于ReentrantLock,并且引入ReentrantLock,可能会令需要开发者混淆。所以ReentrantLock可以认为是

一道开胃小菜而已。

2)非阻塞同步

互斥同步是一种阻塞同步,但是有些情况下,我们不需要互斥,只要能够同步就可以。

java.util.concurrent.atomic.AtomicInteger

就是这样一个自增的方法。

    /**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return current;
}
}

源码里面没有 互斥的操作,就是一直在循环,知道+1满足就退出。

者就是非阻塞同步。

3)无同步

同步只是保证共享数据的手段,如果2个线程没有共享数据,也就不需要同步。

3.锁优化

1)自旋锁

自旋锁有时候会白白的耗用处理器的资源,但是没有任何实际效果。

2)锁消除

如果代码不可能存在共享数据需要同步,编译器就会把锁拿掉

3)锁粗化

原则上锁的互斥模块尽可能的小,但是如果对于同一对象,反复的lock & unlock 尤其是循环体中。

会带来很大的性能损失。

参考:

《深入理解Java虚拟机》周志明

《Java Concurrency in Pratice》

深入理解java虚拟机(7)---线程安全 & 锁优化的更多相关文章

  1. 深入理解Java虚拟机(十)——线程安全与锁优化

    什么是线程安全 当多个线程同时访问一个对象的时候,不需要考虑什么额外的操作就能获取正确的值,就是线程安全的. 线程安全的程度 1.不可变 不可变的对象一定是线程安全的,因为值始终只有一个. final ...

  2. 深入理解Java虚拟机(九)——后端编译与优化

    即时编译器 Java程序最初都是通过解释器进行执行,当发现某个方法或者代码块被运行得非常频繁,这些代码就被认为是热点代码,为了提高这些代码得运行效率,虚拟机会把热点代码编译成本地机器码,并进行优化,运 ...

  3. 深入理解java虚拟机-第13章-线程安全与锁优化

    第十三章 线程安全与锁优化 线程安全 java语言中的线程安全 1 不可变.Immutable 的对象一定是线程安全的 2 绝对线程安全 一个类要达到不管运行时环境如何,调用者都不需要额外的同步措施, ...

  4. 【深入理解JAVA虚拟机】第5部分.高效并发.2.线程安全和锁优化

    1 概述 对于这部分的主题“高效并发”来讲,首先需要保证并发的正确性,然后在此基础上实现高效. 2 线程安全 <Java Concurrency In Practice> 的作者Brian ...

  5. 《深入理解Java虚拟机》-----第12章 Java内存模型与线程

    概述 多任务处理在现代计算机操作系统中几乎已是一项必备的功能了.在许多情况下,让计算机同时去做几件事情,不仅是因为计算机的运算能力强大了,还有一个很重要的原因是计算机的运算速度与它的存储和通信子系统速 ...

  6. 深入理解java虚拟机(6)---内存模型与线程 & Volatile

    其实关于线程的使用,之前已经写过博客讲解过这部分的内容: http://www.cnblogs.com/deman/category/621531.html JVM里面关于多线程的部分,主要是多线程是 ...

  7. 《深入理解Java虚拟机》虚拟机性能监控与故障处理工具

    上节学习回顾 从课本章节划分,<垃圾收集器>和<内存分配策略>这两篇随笔同属一章节,主要是从理论+实验的手段来讲解JVM的内存处理机制.好让我们对JVM运行机制有一个良好的概念 ...

  8. 深入理解Java虚拟机--下

    深入理解Java虚拟机--下 参考:https://www.zybuluo.com/jewes/note/57352 第10章 早期(编译期)优化 10.1 概述 Java语言的"编译期&q ...

  9. 深入理解Java虚拟机--上

    深入理解Java虚拟机--上 第2章 Java内存区域和内存溢出异常 2.2 运行时数据区域 图 2-1 Java虚拟机运行时数据区 2.2.1 程序计数器 程序计数器可以看作是当前线程所执行的字节码 ...

随机推荐

  1. Laravel在不同的环境调用不同的配置文件

    Laravel在不同的环境调用不同的配置文件   Laravel如何在不同的环境调用不同的配置文件?社区这个问题问的蛮多,如何优雅的方法实现呢,应该有好多方法吧,我一般习惯用两种方法,设置环境变量,或 ...

  2. canvas剪裁图片并上传,前端一步到位,无需用到后端

    背景: 当前主流的图片剪裁主要有两种实现方式. 1:flash操作剪裁.2:利用js和dom操作剪裁. 目前看来这个剪裁主要还是先通过前端上传图片到服务器,然后前端操作后把一些坐标和大小数据传到后台, ...

  3. 谷歌联合 Adobe 发布 Noto 字体【免费下载】

    Noto 涵盖了世界上所有主要语言,包括欧洲,非洲,中东,印度语,南亚和东南亚,中亚,美洲和东亚语言.也支持几个少数民族和历史语言.不久前,还发布了针对文.日文.韩文的开源字体——Noto Sans ...

  4. nodejs morgan包

    新建app.js var express = require('express') var logger = require('morgan') var app = express() app.use ...

  5. 通过Foxit和坚果云实现iPad和PC的pdf同步阅读(修改,笔记)

    这是解决我之后上班地铁上看书问题的一个关键部分 一个手持电子设备,不大不小 一个方便做笔记的笔 一个方便做笔记的阅读器软件 方便快速地同步(只同步标记最好了) 在查看很多建议以及自己尝试之后,总结了这 ...

  6. 2015百度之星 IP聚合

    IP聚合 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Descri ...

  7. Unity中简单使用Opengl

    简介 由于项目特殊需求,需要在unity中使用一些OpenGL的东西来绘制图形(PS:其实就是有一个拖尾算法只有OpenGL版本~~~懒得改了,直接在unity中使用OpenGL算了).所以琢磨咯下如 ...

  8. SignalR简单示例教程入门版

    上周五最后一天在公司上班,无聊之余就想做点什么.介于之前有人让我做个简易版的在线聊天的,于是乎就打算花一天时间来弄下关于SignalR的简单教程制作一个在线的聊天的. 1:前端用了国产的一个MVVM框 ...

  9. Python入门笔记(9):元组

    一.元组特性 1.类似列表,但不可变类型,正因如此,它可以做一个字典的key2.当处理一组对象时,这个组默认是元组类型(老写错"元祖")3.所有的多对象,逗号分隔的,没有明确用符号 ...

  10. Python基础:序列(字符串)

    一.概述 字符串 类似于C中的字符数组(功能上更像C++中的string),它是由一个个 字符 组成的序列.与C/C++不同的是,Python中没有 字符 这个类型,而是用 长度为1的字符串 来表示字 ...