1.什么是线程安全?

如果一个类在多线程执行中,在不考虑运行环境的调度干预,也不需要调用代码的协调同步,仍然保证正确地运行,那么这个类就是线程安全的

也就是说,多线程环境下,线程安全的类总是有正确的行为。但是这种类在实际情况中是很少的。

实际情况下的类一般分为5个类别(Java Concurrency in Practice》的作者Brian Goetz给出):

不可变的 这篇文章比较详细的讲述了不可变性。另外设计模式中,还有一个不变模式。

绝对安全/无条件的线程安全,通常来讲这个类“怎么用怎么安全”,但我加了双引号,其实还是要注意的

相对安全/有条件的,方法单个使用是没问题的,但为了处理某些业务按照顺序连续调用需要同步

线程兼容/非线程安全,需要外部同步保证

线程对立,没法协调做到安全

这篇文章的最后给出了这5个级别的更多解释。

2.为什么也好关注线程安全?

随着软硬件的发展,Java代码运行在多处理器环境中。

2.1spring单例,tomcat线程池

spring容器中,类多是单例的。

而web服务器为了提高性能,都是用了线程池处理请求。

2.2提升效率,自己开启新线程

为了提升效率,

应用中也会存在开启多个线程分隔处理多个任务。

或者自己维护线程池处理异步任务的情况。

此时,多个线程的协调和交互都需要关注线程安全。

java中类中的属性会同时有多个线程访问。

3.为什么是类中的属性?方法参数不需要关注线程安全吗?

JVM内存结构图

是属性还是方法参数取决于在jaa运行时共享的资源

这篇文章讲述了java运行时共享的那个资源。

这篇文章从java内存模型的角度分析java中属性和方法参数在底层的实现。

4.怎么才能保证线程安全呢?

需要保证 原子性,可见性,有序性。

5.什么是原子性?为什么要考虑原子性?

一个线程可能对某个属性有多个操作,比如i=i++。可以分解为2个动作

原子性就是这个操作在2步操作中是都必须要完成的,中间不能有其他线程的操作。对其他线程来说这个操作是排他的。

这个保证原子性的过程,需要锁的参与。除了排他锁,还有其他锁。

这篇文章http://ifeve.com/java_lock_see/ 讲的比较详细,也比较有难度。实际上java已经提供了锁的实现,直接使用即可。

加锁同时保证了有序性和可见性。

7,什么是可见性?为什么要考虑可见性?

可见性是值一个线程的操作结果对其他线程可见。

为什么会有不可见的情况呢?这是由java的内存模型决定的,java的内存模型是一个抽象的概念,其具体组成是由cpu缓存,指令缓存等构成的。

为了不受其他因素影响,提升效率,java为每一个线程分配了内存空间叫“工作内存”,执行过程中,

每个线程会从“主内存”拷贝一份数据到工作内存。并在工作内存中计算完成之后将计算结果回写到主内存。比如i++操作。

多个线程的工作内存是不可见的,只有在主内存的数据才可见。

java中的关键字volatile 抑制了一些线程运行上的优化,保证了可见性。比如对volatile变量的操作,任何线程的操作都不再拷贝数据到自己的工作内存,而是直接在主内存中操作。这样保证了多个线程的操作都是可见的,同时也保证了部分的有序性,但是降低了效率。

JVM中每个线程会有自己的栈,而堆是存放各线程所用对象的地方。堆类似于JMM中的主内存,栈中的一部分类似工作内存。

8 .什么是有序性?为什么要考虑有序性?

java为了线程的高效并发执行,也是为了配合工作内存或者说缓存的有效利用,除了工作内存机制的优化之外,还有“指令重排序”。所以需要考虑有序性。

有序性在多线程环境中比较复杂,有序性是指某个操作(操作B)的结果可能需要前一个操作(操作A)的结果前提下完成。

正确的结果应该是操作A-->操作B.不应该出现这种情况操作B-->操作A.

本线程内观察,线程内的所有操作有序,一个线程观察另外一个则无序。

多线程环境中保证有序性,需要遵循happens-before原则,这个原则是重排序的一个默认保证(这个如果不保证,则代码的执行结果不可预见,每次执行都可能不同,这是不可接受的):

Program order rule. 线程内的代码能够保证执行的先后顺序

Monitor lock rule. 对于同一个锁,一个解锁操作一定要发生在时间上后发生的另一个锁定操作之前

Volatile variable rule. 保证前一个对volatile的写操作在后一个volatile的读操作之前

Thread start rule. 一个线程内的任何操作必需在这个线程的start()调用之后

Thread termination rule. 一个线程的所有操作都会在线程终止之前

Interruption rule. 要保证interrupt()的调用在中断检查之前发生

Finalizer rule. 一个对象的终结操作的开始必需在这个对象构造完成之后

Transitivity. 可传递性 9,这8条原则怎么理解呢?

可以参考

http://blog.163.com/javaee_chen/blog/static/179195077201131382128499/

http://ifeve.com/easy-happens-before/

http://javatar.iteye.com/blog/144763

10,双重检查锁定为什么会失效?

双重检查锁定是:

失效的原因主要有:

1.指令重排序

2.内存的可见性

http://ifeve.com/doublecheckedlocking/

java程序中怎么保证多线程的运行安全_Java线程安全问答(草稿)相关推荐

  1. Java 程序中的多线程

    在 Java 程序中使用多线程要比在 C 或 C++ 中容易得多,这是因为 Java 编程语言提供了语言级的支持.本文通过简单的编程示例来说明 Java 程序中的多线程是多么直观.读完本文以后,用户应 ...

  2. java项目运行在浏览器_在 Java 程序中,能在 WWW 浏览器上运行的是 程序。_学小易找答案...

    [简答题]已知:如图, AD 是△ ABC 的角平分线, DE//AC, 交 AB 于点 E , DF//AB ,交 AC 于点 F ,求证: AD ⊥ EF. [简答题]Java语言具有较好的安全性 ...

  3. 在Java程序中打印java运行时参数

    在Java程序中打印java运行时参数 本文是基于CentOS 7.3系统环境,进行java的学习和使用 CentOS 7.3 1. java运行时参数 Java程序在运行时,主要分为两大类参数,一类 ...

  4. java主程序怎样调用子程序_存过和函数以及在Java程序中的调用

    存储过程,函数都是数据库的对象. 创建和调用 存储在数据库中的子程序,是由plsql语言写的,完成特定功能的程序. 函数可以返回值,存过不能返回值.除此之外,一致. create procedure ...

  5. 如何把一个java程序打包成exe文件,运行在没有java虚

    如何把一个java程序打包成exe文件,运行在没有java虚 核心提示:首先,将编译好的程序打包成jar文件,然后做出exe,这样代码就不可见了:但是exe文件在没有安装jre的电脑上不能运行,如果要 ...

  6. java内存漏洞_处理Java程序中的内存漏洞

    Java 程序中也有内存漏洞?当然有.与流行的观念相反,在 Java 编程中,内存治理仍然是需要考虑的问题.在本文中,您将了解到什么会导致内存漏洞以及何时应该关注这些漏洞.您还有机会实践一下在您自己的 ...

  7. 使用comm在java程序中管理本地端口[回钦波:高级软件工程师]

    使用comm在java程序中管理本地端口 最近在做电信项目,遇到一些专业性的问题,在这里和大家一起分享下comm包下的类及如何使用等问题: 在java程序中,为了实现同本地系统的硬件端口(RS-232 ...

  8. mye连接mysql数据库_MySQL_如何在Java程序中访问mysql数据库中的数据并进行简单的操作,在上篇文章给大家介绍了Myeclip - phpStudy...

    如何在Java程序中访问mysql数据库中的数据并进行简单的操作 在上篇文章给大家介绍了Myeclipse连接mysql数据库的方法,通过本文给大家介绍如何在Java程序中访问mysql数据库中的数据 ...

  9. linux java 调用c_Linux上从Java程序中调用C函数

    原则上来说,"100%纯Java"的解决方法是最好的,但有些情况下必须使用本地方法.特别是在以下三种情况: 需要访问Java平台无法访问的系统特性和设备: 通过基准测试,发现Jav ...

最新文章

  1. git 初次push
  2. Spring Boot 中 @EnableXXX 注解的驱动逻辑
  3. java程序分为哪两大类_JAVA程序基础(第1-2章分类)复习-1
  4. 理解VMware Team中的虚拟网络
  5. Webpack-IE低版本兼容指南
  6. java 内部类泛型,java – 使用泛型强制转换为内部类
  7. apache camel 相关配置_小白在 linux 系统部署apache、mysql、Laravel 环境学习笔记!
  8. 几个环境变量说明:ORACLE_SID、DB_NAME、INSTANCE_NAME、DB_DOMIAN、GLOBAL_NAMES
  9. ASP.NET Core 之 Identity 入门(二)
  10. python建立矩阵原理_怎么用python建立矩阵-问答-阿里云开发者社区-阿里云
  11. GBin1推荐:jQuery的滚动插件Waypoints
  12. 数学建模十大经典算法和常用算法
  13. matlab数字图像处理实验
  14. Jupyter notebook 运行时出现 “服务似乎挂掉了,但是会立刻重启的”
  15. Android手势密码
  16. 大数据与人工智能在物联网工程的应用
  17. 初探树莓派与阿里云物联网平台
  18. folly库安装(4)folly依赖的重要组件安装:double-conversion, google-gflags, glog, fmt, googletest, boost等
  19. 为什么Byte是从-128到127?
  20. 原生JavaScript实现 城市二级三级联动

热门文章

  1. 复制(Copying)
  2. 标记-清除(Mark-Sweep)
  3. acquireSharedInterruptibly
  4. AnnotationConfigApplicationContext容器初始化
  5. StringBuilder的toString方法
  6. SpringBoot高级-消息-AmqpAdmin管理组件的使用
  7. java imap 标记已读,JavaMail通过IMAP和POP3接收未读以及设置已读邮件
  8. 书生阅读器打开gd文件出错_CAJ论文怎么打开?
  9. 卡写入保护开关原理_老电工带你解密:插卡取电开关
  10. Cortex-M3-指针和野指针