设计线程安全的类 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,绝对干货满 ...
随机推荐
- ftp获取远程Pdf文件
此程序需要安装ftp服务器,安装adobe reader(我这里使用的adobe reader9.0) 1.部署ftp服务器 将ftp的权限设置为允许匿名访问,部署完成 2.安装adobe reade ...
- 编译安装git
http://zhaohe162.blog.163.com/blog/static/38216797201472185321661/
- 浅谈C语言中断处理机制
一.中断机制 1.实现中断响应和中断返回 当CPU收到中断请求后,能根据具体情况决定是否响应中断,如果CPU没有更急.更重要的工作,则在执行完当前指令后响应这一中断请求.CPU中断响应过程如下:首先, ...
- java中的参数传递——值传递、引用传递
参数是按值而不是按引用传递的说明 Java 应用程序有且仅有的一种参数传递机制,即按值传递. 在 Java 应用程序中永远不会传递对象,而只传递对象引用.因此是按引用传递对象.Java 应用程序按引用 ...
- 小程序swiper配置参数使用
不管什么项目,一个轮播是基本少不了的,现在就来踩下微信小程序的swiper吧! 首先打开文档,可以看到下面这些参数:(https://mp.weixin.qq.com/debug/wxadoc/dev ...
- iOS 学习笔记三【segmentedControl分段控制器详细使用方法】
在iOS开发过程中,分段控制器的使用频率还是蛮高的,下面是我写的一个简单的demo,大家可以把代码直接复制过去,就可以使用,ios9最新支持. // // ViewController.m // 03 ...
- openWRT自学---初始化过程和主要脚本的分析
参考文档: http://wiki.openwrt.org/doc/techref/process.boot http://blog.csdn.net/jk110333/article/details ...
- UVA - 11584 划分字符串的回文串子串; 简单dp
/** 链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34398 UVA - 11584 划分字符串的回文串子串: 简单 ...
- SQLServer -- 竟然默认不区分大小写
SELECT * FROM USER_INFO WHERE USERNAME = :username; 这样的写法,:username的值竟然不区分大小写 原因:数据库的排序规则设置的是Chinese ...
- Python导入不同文件夹下模块
import os.path as osp import sys def add_path(path): if path not in sys.path: sys.path.insert(0, pat ...