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

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

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

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

一、什么是线程安全性

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

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

二、原子性

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. emacs之配置php

    php-setting.el (require 'php-mode) 以后丰富

  2. VS2010 C++环境下DLL和LIB文件的生成与调试 备忘

    利用VS2010工具,调试DLL文件的方法现总结如下: 在一个解决方案中生成两个工程,假设MYDLL和MYDLG两个工程,前者是DLL工程,后者DLG调用前边的DLL工程.设置如下: 目录如下:图,本 ...

  3. CFGym 101161I 题解

    一.题目链接 http://codeforces.com/gym/101161/problem/I 二.题意 给定一棵树,一个初始的省会城市,若干个询问,0表示修改省会城市,1表示查询去省会必须经过指 ...

  4. python3.6 实现AES加密的示例(pyCryptodome)

    当然我也是通过官方推荐,使用下面命令去下载安装的,pip就是好用...    pip install pycryptodome 撸码开始 废话不多说,直接上demo # from Crypto.Has ...

  5. solr统计只返回10或者100个数据的解决办法

    因为我所在的公司为政府做的项目[风险管理系统],其中涉及大量的统计展示,多数以整个市的区划,行业部门等方式返回,在昨天,我发现听过填报单位的方式返回时,始终只有100个数据.通过对比发现,在前辈的代码 ...

  6. django2.0新增功能流程

    1先在 models.py中,创建字段相关的内容,我这里添加一个博客分类的表 定义数据结构的地方 class PostType(models.Model): title = models.CharFi ...

  7. python实现socket上传下载文件-进度条显示

    在python的socket编程中,可以实现上传下载文件,并且在下载的时候,显示进度条,具体的流程如下图所示: 1. 服务器端代码如下: [root@python 519]# cat server.p ...

  8. BTM事务配置

    请参考原贴:http://thinkdifferent.iteye.com/blog/1450433 Tomcat6上配置BTM 博客分类: practice tomcatjava )去http:// ...

  9. leetcode395

    分治法. public class Solution { private int LongestSubstringSub(string s, int k, int start, int end) { ...

  10. linux rz sz 的安装

    先wget获取包wget http://freeware.sgi.com/source/rzsz/rzsz-3.48.tar.gz然后解压tar zxvf  rzsz-3.48.tar.gz进入目录c ...