文档章节

JAVA并发编程学习:构造线程安全的对象

HenrySun
 HenrySun
发布于 2016/08/29 10:02
字数 806
阅读 126
收藏 1

设计线程安全的类

实例限制

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

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

@ThreadSage
public class PersonSet
{
   @GuardedBy("this")
   private final Set<Person> mySet=new HashSet<Person>();
   
    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<String, MutablePoint> locations;
	
	public MonitorVehicleTracker(Map<String, MutablePoint> locations)
	{
		this.locations=deepCopy(locations);
	}
	
	public synchronized Map<String, MutablePoint> 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<String,MutablePoint> deepCopy(Map<String, MutablePoint> m)
	{
		Map<String,MutablePoint> result=new HashMap<String,MutablePoint>();
		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

© 著作权归作者所有

HenrySun
粉丝 89
博文 121
码字总数 41919
作品 0
深圳
高级程序员
私信 提问
java多线程系列:通过对战游戏学习CyclicBarrier

CyclicBarrier是java.util.concurrent包下面的一个工具类,字面意思是可循环使用(Cyclic)的屏障(Barrier),通过它可以实现让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一...

huangzd
2018/01/06
0
0
聊一聊并发编程的那些事(内含源码及面试题)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/t4i2b10X4c22nF6A/article/details/82889698 导读:之前写了一系列关于并发编程的文章,也对今年的一些大型互...

JAVA高级架构v
2018/09/28
0
0
《Java并发编程实战》读书笔记一:基础知识

一、线程安全性 一个对象是否是需要是线性安全的,取决于它是否需要被多个线程访问 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不...

小七奇奇
2018/08/17
0
0
基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程

许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存、CPU、缓存等予以说明。实际上,在实...

leoliu168
2018/11/08
0
0
(三)Java并发学习笔记--线程封闭

线程封闭 实现好的并发是一件困难的事情,所以很多时候我们都想躲避并发。避免并发最简单的方法就是线程封闭。什么是线程封闭呢? 就是把对象封装到一个线程里,只有这一个线程能看到此对象。...

潘天涯
2018/08/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

spring 本类中方法调用另外一个方法事务不生效

1、在spring配置文件中添加 <aop:aspectj-autoproxy expose-proxy="true"/> 声明自动代理 2、AopContext.currentProxy()来获取代理类 3、使用代理类proxy进行代理调用内部声明了事务的方法 ......

重城重楼
31分钟前
5
0
项目 banner 乱弹

------------------------------------------ 村上春树 ------------------------------------- 如果我爱你,而你也正巧爱我,你头发乱了的时候,我会笑笑地替你拨一拨,然后手还留恋地在你...

宿小帅
43分钟前
3
0
PHP获取未来七天的日期和星期

php获取未来七天的日期和星期代码 第一步:获取需要天数的日期,然后调用函数 //获取未来七天的日期 for($i=1;$i<8;$i++){ $dateArray[$i]=date('Y-m-d',strtotime(d...

一只懒猫-
54分钟前
2
0
总结:IO模型

分类 多路复用 参考文章: https://www.jianshu.com/p/6a6845464770 https://www.cnblogs.com/zingp/p/6863170.html https://blog.csdn.net/sehanlingfeng/article/details/78920423......

浮躁的码农
58分钟前
2
0
fabric-sdk-java 1.4安装说明

Hyperledger Fabric Java SDK是开发基于Hyperledger Fabric区块链的Java应用之必备开发包。本文将介绍如何在Maven、Gradle和Eclipse中安装使用最新1.4版本的Hyperledger Fabric Java SDK。 ...

汇智网教程
59分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部