JAVA并发编程之线程安全性
1、一个对象是否是线程安全的,取决于它是否被多个线程访问。想要使得线程安全,需要通过同步机制来协同对对象可变状态的访问。
2、修复多线程访问可变状态变量出现的错误:1、程序间不共享状态变量 2、状态变量修改为不可变 3、使用同步
3、无状态的对象一定是线程安全的,一个类中如果没有包含任何域及其他类域的引用,则这个类是个无状态的类,类的对象是无状态对象。
4、线程安全下的一些概念:
1、在并发编程中,如果一个包含状态的对象,在执行过程中操作不具备原子性,则会使此变量发生偏差。
2、在并发编程中,如果一个包含状态的对象,在操作过程中存在多个竞态条件,结果会变不可靠。因为后执行的操作,可能会基于前一个操作的状态去执行某个操作,但前一个操作的结果可能会失效,导致后一个操作从全局看是错误的,这叫做先检查后执行错误。
3、复合操作:先检查后执行;读取-修改-写入
4、加锁机制
5、内置锁:同步代码块包括两部分:一个作为锁的对象引用,另一个作为锁保护的代码块。Java内置锁相当于一个互斥锁。
6、重入锁:指如果某个线程已经获取了某个锁,在流程处理过程中,又重新去获取这个锁,则将会成功。
7、用锁来保护状态:由于锁能达到代码路径以串行执行,因此可以通过锁来构造一些协议,实现对共享状态的独占访问,遵循这些协议,则可达到状态一致性目的。避免产生竞态条件:原子操作,比如命中计数器的复合操作或者延迟初始化操作都需要是原子性的。如果在复合操作过程中持有一个锁,则复合操作会变成一个原子操作。但仅仅将复合操作封装到一个同步代码块中是不够的,需要在访问某个变量的所有位置上都使用同步,都使用同一个锁。
对于可能被多个线程同时访问的可变状态变量,在访问时需要同一个锁,这个变量就是被这个锁保护的。
每个对象虽然可以通过一个内置锁受到保护,但这种锁并不能阻止其他线程去访问这个对象,因为某个线程在获得这个对象的锁以后,并不能阻止的是其它线程去获得这个锁,想要对象中的共享状态变量安全,需要自行构造加锁协议或者同步策略,在程序中要自始至终的使用这个策略。
以上的意思是:如果某个对象中的复合操作或者延迟操作想要得到线程安全保护,那么只在这个对象的这些操作上进行内置锁保护是不够的,因为其他线程也会去访问这个对象的共享变量,如果访问的获取操作或者修改操作,那么这个共享变量就变得不安全,怎么达到共享安全呢,需要在这个共享变量的操作上全部使用锁或者不同的策略,这样不管执行什么操作,都是安全的。
还有,如果我们能达到在访问某个共享状态变量时候,都需要持有同一个锁才能访问这个共享状态变量,那么也能达到线程安全,这种安全是建立在这个锁保护的基础上。
JAVA并发编程之线程安全性的更多相关文章
- Java并发编程 (四) 线程安全性
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.线程安全性-原子性-atomic-1 1.线程安全性 定义: 当某个线程访问某个类时,不管运行时环境 ...
- Java并发编程 (五) 线程安全性
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.安全发布对象-发布与逸出 1.发布与逸出定义 发布对象 : 使一个对象能够被当前范围之外的代码所使用 ...
- Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition
Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...
- Java并发编程:线程池的使用(转)
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java并发编程:线程控制
在上一篇文章中(Java并发编程:线程的基本状态)我们介绍了线程状态的 5 种基本状态以及线程的声明周期.这篇文章将深入讲解Java如何对线程进行状态控制,比如:如何将一个线程从一个状态转到另一个状态 ...
- Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)
Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...
- (转)Java并发编程:线程池的使用
背景:线程池在面试时候经常遇到,反复出现的问题就是理解不深入,不能做到游刃有余.所以这篇博客是要深入总结线程池的使用. ThreadPoolExecutor的继承关系 线程池的原理 1.线程池状态(4 ...
- Java并发编程:线程池的使用(转载)
转载自:https://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...
随机推荐
- 淘淘商城之httpclient
一.什么是httpclient HTTP 协议可能是现在 Internet 上使用得最多.最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议 来访问网络资源:虽然在 JDK 的 ...
- 【笔记3-用户模块】从0开始 独立完成企业级Java电商网站开发(服务端)
数据表结构设计 关系设计 为什么不用外键? 分库分表有外键会非常麻烦,清洗数据也很麻烦.数据库内置触发器也不适合采用. 查业务问题的后悔药--时间戳 create_time 数据创建时间 update ...
- 【Go语言系列】1.4、GO语言简介:第一个Go语言程序
接下来我们来编写第一个 Go 程序 hello.go(Go 语言源文件的扩展是 .go),代码如下: // 声明 main 包 package main import ( "fmt" ...
- Linux学习:进入与退出系统
进入Linux系统:必须要输入用户的账号,在系统安装过程中可以创建以下两种帐号: 1.root--超级用户帐号(系统管理员),使用这个帐号可以在系统中做任何事情. 2.普通用户--这个帐号供普通用户使 ...
- 2019牛客暑期多校训练营(第七场)A String (字符串的最小表示)
思路 这题思路如果是递归的话,应该是比较正确的.但是实际上只用切割两次就可以了. 先把原串从后向前切割一次,再把每一部分切割一次. 切两次的思路实际上是有漏洞的. 递归的思路,终点是,如果串长为1,或 ...
- ES5-bind用法及与以前的apply和call
当我们调用一个函数的时候,函数中的this一般是指向调用者的.但是我们其实可以在调用函数的时候,传入一个对象,让函数中的this指向我们传入的对象,而不是调用者本身. apply,call,bind都 ...
- PhpStorm For Mac 安装使用及 Php 开发的 ‘Hello World’
PHP全称为:Hypertext Preprocessor,中文名为:『超文本预处理 器』是一种通用开源脚本语言,主要用于Web应用开发(俗称做网站或 者做后台!) 编译软件:PHPStorm for ...
- mcast_get_if函数
#include <errno.h> int sockfd_to_family(int); int mcast_get_if(int sockfd) { switch (sockfd_to ...
- EASYUI combobox firefox 下不支持中文检索
firefox 中文录入因为输入法的问题,无法出发检索的事件.网上的方法试过还是没有解决. 于是使用录入时新增一个模拟键shift,触发keydown事件,最终实现需要的效果. $("inp ...
- jqGird错误“decimalSeparator”的解决办法
在使用jqGrid的过程中,突然出现以下错误: jquery.jqGrid.js:15016 Uncaught TypeError: Cannot read property 'decimalSepa ...