设计线程安全的类

实例限制

当一个对象被另一个对象封装时,所有访问被被封装对象的代码路径就是全部可知的,这相比于让对象可被整个系统访问来说,更容易对代码路径进行分析。将数据封装在对象内部,把对数据的访问限制在对象的方法上,更易确保线程在访问数据时总能获得正确的锁

被限制对象一定不能溢出到它的期望可用的范围之外。可以把对象限制在本地变量、类的实例(比如私有类的成员)或线程(比如对象在线程内部从一个方法传递到另一个方法,不过前提是该对象不被跨线程共享),下面的例子未对Person的线程安全性作任何假设,但如果它是可变的,那么可能还需要额外同步

@ThreadSage

public class PersonSet

{

@GuardedBy("this")

private final Set mySet=new HashSet();

public synchronized void addPerson(Person p)

{

mySet.add(p);

}

public synchronized boolean containsPerson(Person p)

{

return mySet.contains(p);

}

}

监视器

使用私有锁对象,而不是对象的内部锁(或任何其他可公共访问的锁)

public class PrivateLock

{

private final Object myLock=new Object();

@GuardedBy("myLock") Widget widget;

void somenMethod()

{

synchronized(myLock)

{

//访问或修改widget的状态

}

}

}

范例:机动车追踪器

package com.henrysun.javaSE.bfbc;

import java.util.Collections;

import java.util.HashMap;

import java.util.Map;

import org.apache.http.annotation.GuardedBy;

/**

* 线程安全类,JAVA监视器模式

* 范例:机动车追踪器

* 一个用于调度出租车,警车,货运卡车等机动车的“机动车追踪器”,每一辆机动车都有一个String标识

* 并有一个与之对应的位置(X,Y),视图线程和多个更新线程会并发的访问数据模型

* @author Sam Flynn

*

*/

public class MonitorVehicleTracker {

@GuardedBy("this")

private final Map locations;

public MonitorVehicleTracker(Map locations)

{

this.locations=deepCopy(locations);

}

public synchronized Map getLocations() {

return deepCopy(locations);

}

public synchronized MutablePoint getLocation(String id) {

MutablePoint loc=locations.get(id);

return loc==null?null:new MutablePoint(loc);

}

public synchronized void setLocation(String id,int x,int y)

{

MutablePoint loc=locations.get(id);

if(loc==null)

{

throw new IllegalArgumentException("No such ID:"+id);

}

loc.x=x;

loc.y=y;

}

private static Map deepCopy(Map m)

{

Map result=new HashMap();

for(String id:m.keySet())

{

result.put(id, new MutablePoint(m.get(id)));

}

return Collections.unmodifiableMap(result);

}

}

/**

* 可变point

* @author Sam Flynn

*

*/

class MutablePoint

{

public int x,y;

public MutablePoint(){x=0;y=0;}

public MutablePoint(MutablePoint p)

{

this.x=p.x;

this.y=p.y;

}

}

先复制可变的数据,再返回给用户,这种实现方式只能简单的维护线程安全。如果locations集合不是非常大的话,这种做法通常不会造成性能问题。每次调用getLocations前先复制全部数据还会产生另一种副作用-即使真实的location已经改变,返回的容器的内容仍然不会改变

委托线程安全

我们向一个无状态的类(假设A)中添加一个线程安全的类型(假设B)的属性,所得组合对象仍然是线程安全的,因为A的状态就是线程安全类B的状态,并且A没有对B的状态增加额外的有效性的约束,可以说A将它的线程安全性委托给了B

java 对象 线程安全_JAVA并发编程学习:构造线程安全的对象相关推荐

  1. java中解决脏读_java并发编程学习之脏读代码示例及处理

    使用interrupt()中断线程     当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一个标志,表示它已经被中断,并立即 ...

  2. java公平锁和非公平锁_java并发编程学习之再谈公平锁和非公平锁

    在java并发编程学习之显示锁Lock里有提过公平锁和非公平锁,我们知道他的使用方式,以及非公平锁的性能较高,在AQS源码分析的基础上,我们看看NonfairSync和FairSync的区别在什么地方 ...

  3. libevent c++高并发网络编程_高并发编程学习(2)——线程通信详解

    前序文章 高并发编程学习(1)--并发基础 - https://www.wmyskxz.com/2019/11/26/gao-bing-fa-bian-cheng-xue-xi-1-bing-fa-j ...

  4. 高并发编程学习(2)——线程通信详解

    前序文章 高并发编程学习(1)--并发基础 - https://www.wmyskxz.com/2019/11/26/gao-bing-fa-bian-cheng-xue-xi-1-bing-fa-j ...

  5. 网易云课堂微专业--Java高级开发工程师--多线程并发编程--学习笔记(二)

    文章目录 第一章 多线程并发编程 第二节 线程安全问题 1.2.1 线程安全之可见性问题 多线程中的问题 从内存结构到内存模型 工作内存缓存 指令重排序 内存模型的含义 Shared Variable ...

  6. java后验条件_JAVA并发实战学习笔记——3,4章~

    JAVA并发实战学习笔记 第三章 对象的共享 失效数据: java程序实际运行中会出现①程序执行顺序对打乱:②数据对其它线程不可见--两种情况 上述两种情况导致在缺乏同步的程序中出现失效数据这一现象, ...

  7. java 共享锁 独占锁_Java并发编程锁之独占公平锁与非公平锁比较

    Java并发编程锁之独占公平锁与非公平锁比较 公平锁和非公平锁理解: 在上一篇文章中,我们知道了非公平锁.其实Java中还存在着公平锁呢.公平二字怎么理解呢?和我们现实理解是一样的.大家取排队本着先来 ...

  8. synchronized原理_Java并发编程 -- synchronized保证线程安全的原理

    线程安全是并发编程中的重要关注点,应该注意到的是,造成线程安全问题的主要诱因有两点,一是存在共享数据(也称临界资源),二是存在多条线程共同操作共享数据.因此为了解决这个问题,我们可能需要这样一个方案, ...

  9. java线程池_Java 并发编程 线程池源码实战

    作者 | 马启航 杏仁后端工程师.「我头发还多,你们呢?」 一.概述 笔者在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写 ...

最新文章

  1. 华为oj平台的新网址
  2. 机器学习实战指南:如何入手第一个机器学习项目?
  3. c语言形参指针 实参数组,《C语言程序设计》中的指针形参和函数体中数组实参问题的教学研究.pdf...
  4. Greenplum使用简明手册
  5. java,java基础面试笔试题
  6. 吴恩达深度学习之五《序列模型》学习笔记
  7. python multiprocessing 批量下载图片+tqdm
  8. 从零基础入门Tensorflow2.0 ----二、4.3 wide deep 模型(多输入)
  9. 【深度学习论文】:U-Net
  10. 标准电阻阻值速查表及由来
  11. exosip鉴权及使用
  12. 代码调试全指南-自然语言处理-基于预训练模型的方法,车万翔
  13. html+css网页开发 之 头部导航条(logo、导航栏、搜索框)
  14. get inkey、get input中,7 bit default 字符与ucs2字符的差异
  15. python如何用一行代码生成[1,4,9,16,25,36,49,64,81,100]
  16. C#调用触摸屏小键盘
  17. [转载]JS和AS交互 作者:ludanlove
  18. 身份证扫描识别OCR技术的应用场景
  19. java计算机毕业设计流行病调查平台源码+数据库+系统+lw文档+mybatis+运行部署
  20. 技术分享 | 实战 MySQL 8.0.17 Clone Plugin

热门文章

  1. js中值得推荐的Memoization
  2. 基于ASP.NET的开源Blog程序总结
  3. 我年龄大了还学的动it吗
  4. Oracle - SELECT 1 FROM table; SELECT COUNT(1) FROM table;
  5. 苹果推送通知服务(APNs)编程(转)详细步骤
  6. 论计算机专业毕业生的人文素养
  7. HXSafeGuard工程通过VS2010编译未安装VS2008出现以下错误
  8. VS2010编译器经常遇到的小问题
  9. NGUI_2.6.3_系列教程一
  10. 大数据之-Hadoop之HDFS的API操作_查看文件的详情---大数据之hadoop工作笔记0061