设计线程安全的类 VS 发布线程安全的对象
一、设计线程安全的类
步骤:
找出构成对象状态的所有变量
找出约束状态变量的不变性条件
建立对象状态的并发访问策略
1.在现有的线程安全类中添加功能
(1)重用能减低工作量和提高正确性
(2)如果底层的类改变了同步策略,使用不同的锁来保护它的状态,则子类会被破坏
class BetterVector<E> extends Vector<E>{
public synchronized boolean putIfAbsent(E e){
boolean absent = !contains(e);
if(absent){
add(e);
}
return absent;
}
}
2.客户端加锁机制
(1)对于使用对象X的客户端,如果知道X使用的是什么锁,则使用X本身用于保护其状态的锁,来保护这段客户端代码
(2)同样会破坏同步策略的封装
A.错误示例:
class ListHelper<E>{
public List<E> list = Collections.synchronizedList(new ArrayList<E>());
public synchronized boolean putIfAbsent(E e){
boolean absent = !list.contains(e);
if(absent){
list.add(e);
}
return absent;
}
}
B.正确示例:
class ListHelper<E>{
public List<E> list = Collections.synchronizedList(new ArrayList<E>());
public boolean putIfAbsent(E e){
synchronized(list){
boolean absent = !list.contains(e);
if(absent){
list.add(e);
}
return absent;
}
}
}
3.组合:推荐方式
class ImprovedList<E> implements List<E>{
private final List<E> list;
public ImprovedList(List<E> list){
this.list = list;
}
public synchronized boolean putIfAbsent(E e){
boolean absent = !list.contains(e);
if(absent){
list.add(e);
}
return absent;
}
public synchronized boolean add(E e) {
//委托.....
}
}
二、发布线程安全的对象
1. 发布对象:使对象能在当前作用域之外的代码中使用。既将对象的引用传递到其他类的变量和方法。
(1)变量的静态初始化
(2)声明为volatile变量 或 AtomicReferance对象
(3)声明为final变量
(4)将变量保存在线程安全的容器中(既保存在一个由锁保护的域中)
2. 成员变量的初始化:
(1)直接初始化
(2)构造函数初始化
3. 不可变对象、可变对象
在Java内存模型中,final域能确保初始化过程的安全性,从而可以不受限制的访问不可变对象,并在共享这些对象时无需同步。
在可变对象基础上构建的不可变类:虽然Set对象是可变的,但Set对象通过ThreeStooges的构造函数后,无法对其修改。
public final class ThreeStooges {
private final Set<String> stooges = new HashSet<String>();
public ThreeStooges(){
stooges.add("A");
stooges.add("B");
stooges.add("C");
}
public boolean isStooge(String name){
return stooges.contains(name);
}
}
设计线程安全的类 VS 发布线程安全的对象的更多相关文章
- Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量
Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量 一丶线程的理论知识 什么是线程: 1.线程是一堆指令,是操作系统调度 ...
- Java自学-多线程 线程安全的类
Java常见的线程安全相关的面试题 步骤 1 : HashMap和Hashtable的区别 HashMap和Hashtable都实现了Map接口,都是键值对保存数据的方式 区别1: HashMap可以 ...
- Java线程池 ThreadPoolExecutor类
什么是线程池? java线程池是将大量的线程集中管理的类, 包括对线程的创建, 资源的管理, 线程生命周期的管理. 当系统中存在大量的异步任务的时候就考虑使用java线程池管理所有的线程, 从而减少系 ...
- C# 线程(二):关于线程的相关概念
From : http://kb.cnblogs.com/page/42528/ 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源. 而一个进程又 ...
- Java并发编程(十)设计线程安全的类
待续... 线程安全的类 之前学了很多线程安全的知识,现在导致了我每次用一个类或者做一个操作我就会去想是不是线程安全的.如果每次都这样的考虑的话就很蛋疼了,这里的思路是,将现有的线程安全组件组合为更大 ...
- Java线程与并发库高级应用-线程范围内共享数据ThreadLocal类
1.线程范围内共享变量 1.1 前奏: 使用一个Map来实现线程范围内共享变量 public class ThreadScopeShareData { static Map<Thread, In ...
- Java 类 ThreadLocal 本地线程变量
前言:工作中将要使用ThreadLocal,先学习总结一波.有不对的地方欢迎评论指出. 定义 ThreadLocal并不是一个Thread,而是Thread的局部变量.这些变量不同于它们的普通对应物, ...
- 【Thread】java线程之对象锁、类锁、线程安全
说明: 1.个人技术也不咋滴.也没在项目中写过线程,以下全是根据自己的理解写的.所以,仅供参考及希望指出不同的观点. 2.其实想把代码的github贴出来,但还是推荐在初学的您多亲自写一下,就没贴出来 ...
- java线程并发工具类
本次内容主要讲Fork-Join.CountDownLatch.CyclicBarrier以及Callable.Future和FutureTask,最后再手写一个自己的FutureTask,绝对干货满 ...
随机推荐
- 把sqlserver查询结果复制到Excel出现数据记录遗漏
问题:今天在sqlserver查询,总共有10000记录,把结果复制到Excel,发现少掉352条,用导出csv也是如此. 原因:经排查发现缺少的记录是因为商品名称字段包含英文双引号". 解 ...
- 使用NPOI读取Excel出错
使用NPOI读取Excel出错,错误信息:java.io.IOException: Invalid header signature; read 4503608217567241, expected ...
- vivado与modelsim的联合仿真(一)
vivado软件中也自带仿真工具,但用了几天之后感觉仿真速度有点慢,至少比modelsim慢挺多的.而modelsim是我比较熟悉的一款仿真软件,固然选它作为设计功能的验证.为了将vivado和mod ...
- 红茶一杯话Binder (初始篇)
1 什么是Binder? 简单地说,Binder是Android平 台上的一种跨进程交互技术.该技术最早并不是由Google公司提出的,它的前身是Be Inc公司开发的OpenBinder,而且在Pa ...
- libevent源码学习_event结构体
在libevent中最重要的结构体莫过于event和event_base了,下面对于这2个结构体进行分析. 1.结构体event,位于:event.h struct event { /* * 双向链表 ...
- 使用NGINX反向代理做小偷站
用Nginx的反向代理可以轻松山寨对方的网站,但是反向代理后的网站还是有对方的绝对链接时,怎么办?所以要用替换链接方法. 1 使用官方的的模块 编译参数–with-http_sub_moduleub_ ...
- java 无状态和有状态区别
诸位Java程序员,想必大家对SimpleDateFormat并不陌生.不过,你是否知道,SimpleDateFormat不是线程安全的(thread safe).这意味着,下面的代码是错误的: ...
- Cassandra第一次使用
在FreeBSD上安装Cassandra: # pkg install cassandra2找了半天Cassandra的配置文件,原来安装位置是在这: /usr/local/share/cassand ...
- 面向对象JSON的继承(复制)与函数的继承(复制)
今天这里和大家分享下如何复制对象 的属性 创建 对象的方式有三种,这里和大家分享下最常用的几种 1.JSON格式的方式创建对象 2.用函数的方式创建,然后用new关键字实例化对象,关于this的指向问 ...
- mysql 1005 错误
建立外键的时候两个 表的相对应的 类型不一致!