一个对象是否需要是线程安全的取决于它是否被多个线程访问

多个线程访问同一个可变状态量时如果没有使用正确的同步规则,就有可能出错。解决办法:

  • 不在线程之间共享该变量
  • 将状态变量修改为不可变的
  • 在访问状态变量时使用同步机制

完全由线程安全类构造的程序也不一定是线程安全的,线程安全类中也可以包含非线程安全的类

一、什么是线程安全性

线程安全是指多个线程在访问一个类时,如果不需要额外的同步,这个类的行为仍然是正确的。(因为线程安全类中封装了必要的同步代码)

一个无状态的类是线程安全的。无状态类是指不包含任何域或也没有引用其它类的域。一次特定计算的瞬间状态,会唯一存在本地变量中。

二、原子性

1、竞争条件:由于不恰当的执行时许而出现了不正确的运行结果,当计算的正确性取决于交叉执行的顺序时

错误原因:基于一个可能失效的观察结果进行下一步操作

例1:读取-修改-写入 操作: 当两个线程交叉执行并同时读取到了相同的值,addOne操作便造成了偏差-1的结果。

1 public class Test {
2 private int x = 0;
3 public void addOne(){
4 x++;
5 }
6 }

例2:先检测后执行 操作:没有进行同步操作的单件模式

2、复合操作

概念:包含一组必须以原子方式执行的操作以保证线程的安全性

原子操作是线程安全的 vs 竞争条件是不安全的

在无状态的类中加入一个确保线程安全的状态可以保证该类仍未线程安全的,但加入多个线程安全状态时没有办法保证。

三、加锁机制

1、内置锁:java提供了强制原子性的内置锁机制:synchronized 块,每个java对象都可作为锁,称为内置锁或监视锁

  • synchronized(lock){访问或修改共享变量}
  • synchronized方法为保证整个方法体为原子的,lock为this
  • 静态synchronized方法以Class对象为锁

最多只有一个对象持有该锁,进入同步代码块获得锁,出代码块释放锁

synchronized特性不能被继承,即覆盖方法需要也写synchronized关键字

2、重入

内置锁是可以重入的,即某个线程可以获得它已经持有的锁。(例同步子类方法调用父类方法super.method()会请求它已经有的锁)

JVM提供锁内线程计数器予以保证正确释放锁

四、用锁来保护对象

锁使受保护的代码以串行形式执行。

对于可能被多个线程访问的状态变量,访问它的时候都要加锁,不只是在写入时加锁。

每一个共享的或可变的状态都应该由一个锁保护

锁机制仅仅阻止了其他线程获得同一个锁,而不能防止访问对象

即使每个方法都使用了同步机制,但由他们呢构成的复合操作不一定保证并发正确。

1 public add(E e){
2 if(!vector.contains(e))
3 vector.add(e);
4 }

五、活跃性与性能

如果对整个services方法加锁,方法内有某个计算耗时较长时,那么将严重影响效率

修改代码后将绿色箭头指的大计算量部分重同步代码中取出,可以并发操作,改进性能

java并发编程实战:第二章----线程安全性的更多相关文章

  1. JAVA并发编程实战---第二章:线程安全性

    对象的状态是指存储在状态变量中的数据.对象的状态可能包括其他依赖对象的域.例如HashMap的状态不仅存储在HashMap本身,还存储在许多Map.Entry对象中.对象的状态中包含了任何可能影响其外 ...

  2. Java并发编程实战4章

    第4章主要介绍如何构造线程安全类. 在设计线程安全类的过程中,需要包含以下三个基本要素: 找出构成对象状态的所有变量. 找出约束状态变量的不变性条件. 建立对象状态的并发访问管理策略. 构造线程安全类 ...

  3. java并发编程实战《七》安全性、活跃性以及性能问题

    安全性.活跃性以及性能问题 安全性问题 那什么是线程安全呢?其实本质上就是正确性,而正确性的含义就是程序按照我们期望的执行,不要让我们感到意外. 存在共享数据并且该数据会发生变化,通俗地讲就是有多个线 ...

  4. Java并发编程实战3章

    1.同步包括两方面:原子性和可见性. 2.可见性:因为在多线程程序中,如果没有采用正确的同步,有些线程就会得到失效数据. Java内存模型要求,变量的读取操作和写入操作都必须是原子操作,但对于非vol ...

  5. 【java并发编程实战】-----线程基本概念

    学习Java并发已经有一个多月了,感觉有些东西学习一会儿了就会忘记,做了一些笔记但是不系统,对于Java并发这么大的"系统",需要自己好好总结.整理才能征服它.希望同仁们一起来学习 ...

  6. Java并发编程实战---第六章:任务执行

    废话开篇 今天开始学习Java并发编程实战,很多大牛都推荐,所以为了能在并发编程的道路上留下点书本上的知识,所以也就有了这篇博文.今天主要学习的是任务执行章节,主要讲了任务执行定义.Executor. ...

  7. 《Java并发编程实战》/童云兰译【PDF】下载

    <Java并发编程实战>/童云兰译[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062521 内容简介 本书深入浅出地介绍了Jav ...

  8. 《java并发编程实战》笔记

    <java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为:  Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...

  9. [书籍翻译] 《JavaScript并发编程》 第二章 JavaScript运行模型

    本文是我翻译<JavaScript Concurrency>书籍的第二章 JavaScript运行模型,该书主要以Promises.Generator.Web workers等技术来讲解J ...

  10. Java并发编程实战 04死锁了怎么办?

    Java并发编程文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 前提 在第三篇 ...

随机推荐

  1. 你正在从一个声称代表如下的证书颁发机构安装证书 alipay truest network,希望能知道程序是怎么实现的或相关资料

    你正在从一个声称代表如下的证书颁发机构安装证书 alipay truest network,希望能知道程序是怎么实现的或相关资料

  2. column count of mysql.proc is wrong. expected 20,found 16. the table is probably corruptd.

    1558 1547 column count of mysql.proc is wrong. expected 20,found 16. the table is probably corruptd. ...

  3. 02 - Unit010:关联映射

    关联映射 什么是? 数据库中有关联关系的表,通过实体对象引用的方式体现出来,叫关联映射. 为什么? 将多表的记录封装成实体对象. 何时用? 对数据库中的表进行多表查询时. 怎么用? cn_user-- ...

  4. SpringMVC+hibernate4事务处理

    首先spring-hibernate.xml里配置事务: <!-- 配置事务管理器 --> <bean id="transactionManager" class ...

  5. char、varchar、varchar2区别

    char varchar varchar2 的区别 区别:1.CHAR的长度是固定的,而VARCHAR2的长度是可以变化的, 比如,存储字符串“abc",对于CHAR (20),表示你存储的 ...

  6. 马士兵Spring-dataSource

    一.简单使用例子: 这里使用commons.dbcp: beanx.xml配置: <?xml version="1.0" encoding="UTF-8" ...

  7. jmeter录制https请求时,浏览器每一个请求都 跳 不安全访问页面的解决方法

    1.关闭所有浏览器 2,使用终端 输入 : /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --ignore-certif ...

  8. CentOS 添加新硬件硬盘,扩展空间而无需重启虚拟机

    运行如下命令,通过重新扫描 SCSI (注:Small Computer System Interface 小型计算机系统接口)总线并添加 SCSI 设备,系统就可以扩展操作系统的物理卷磁盘空间,而且 ...

  9. Fatal error: Call to undefined function Think\C() in /var/www/html/ceshi.hzheee.com/think/ThinkPHP/Library/Think/Think.class.php on line 334 这个问题解决

    当APP_DEBUG为true时,包含图中这个文件,文件中又引导包含这些库文件,可以看出安装thinkphp3.2.3时ThinkPHP/Common/下是functions.php,把它改成func ...

  10. sql多表更新使用别名(小技巧)

    update     A set     A.CityRegionID=B.ParentID,     A.CityName=(select RegionName from Common_Region ...