线程安全的类

在这里插入图片描述几乎所有的对象都是组合对象,一个人的力量总是有限的,线程安全也不例外。
线程安全的类该咋写?首先需要明确线程安全类有哪些要求?1.确定限制状态变量的不变约束;2.制定一个并发管理访问对象状态的策略;3.确定对象状态是由哪些变量构成的;我们都知道面向对象的三大特征之一就是封装,封装是保证线程安全性的利器,那是不是就意味着没有封装就是不安全?倒也没有那么绝对,其实,把所有的状态都保存在公共静态域中也是可以写出线程安全的程序的,这样的程序比起封装后的程序有什么不好呢?这种程序的安全只是一种可能性,不是一定会发生的事情,而且我们很那验证他是否总是安全,而且也很难做到修改他们的时候不破坏他们的线程安全性;我们言归正传,以上三个要素都提到了对象的状态,提到对象的状态,就不能不提起域,这里的域需要分类讨论:第一种:如果对象的域都是primitive(基本类型),这些域组成了对象的完整状态;第二种:如果一个对象有n个primitive fields(基本域),那么对象的状态就是域值组成的n-tuple(n元组);第三种:如果一个对象的域引用了其他对象,那他的状态也同时包含了被引用对象的域;运筹帷幄-同步策略同步策略定义了对象如何协调对其状态的访问,同步策略把不可变性、线程限制和锁都结合起来了://使用java监视器模式的简单线程安全计数器@ThreadSafepublic final class Counter{@GuardedBy(“this”) private long value=0; public synchronized long getValue(){return value; } public synchronized long increment(){ if(value==Long.MAX_VALUE) throw new IllegalStateException(“counter overflow”);{ return ++value; } }}合并同类项-同步需求的收集对当前的类的对象的状态进行判断的目的就是为了确保在并发访问的状态下类的不变约束,对象和变量拥有一个state space(状态空间),状态空间越小越容易判断,为了简化操作,尽量使用final类型的域;通过不可变约束很多类就可以判断某一种状态时合法的还是非法的,后验条件会指出某种state transitiions(状态转换),是非法的,如果下一个状态源自当前状态那么该操作必须是复合操作,不变约束和后验条件施加在状态以及状态转换上的约束引入了额外的同步与封装的需要;如果某些状态有非法的可能性,那么就必须封装该状态下的状态变量,否则不是非法也是非法的了;如果一个操作的过程中有非法状态转换的可能性,那么该操作必须是原子的;一个类的不变约束可以约束多个状态变量,这种多变量的不变约束必须在单一的原子操作中获取或更新相互关联的变量;没办法,你就得依赖我-状态依赖如果一个操作存在基于状态的的先验条件,那么这就是state-dependent(状态依赖)的;状态依赖只能活在多线程的环境里,因为在单线程的环境下,一旦操作不满足先验条件就失败了,单线程就是没的选,多线程就不一样,原本为false的先验条件可能会由于其他线程的活动变为true,这就说明等待的重要性,多线程的环境下如果发现先验条件为false了先不要急,一定要先等待,很有可能过一会先验条件就变为了true;我封装的就是我的很多情况下,封装性和所有权是兄弟,对象拥有他的状态,还拥有他封装的状态,拥有给定状态的所有者决定了用于维护变量状态的完整性的锁协议,所有权就是控制权,除非你把引用发布到可变对象上,你就失去了独有的控制权,取而代之的是“共享控制权”,如果一个构造函数不是明确设计用来转换传递对象的所有权的话当前的这个类就不会拥有由构造函数传递来的对象;那这个所有权有没有例外呢?有的,容器类(特指容器拥有容器状态而代码存储在容器的对象)就通常表现成“所有权分离”的形式;封装的另一个名字-限制封装简化了类的线程安全,这也叫做instance confinement(实例限制),当一个对象被另一个对象封装时,所有访问被封装对象的路径都是可知的,封装更多的是针对数据:封装在对象的数据,而限制主要是针对函数,更多的是指的访问这个动作:访问对象的内部的数据;@ThreadSafepublic class PersonSet{@GuardedBy(“this”) private final Set mySet=new HashSet(); public synchronized void addPerson(Person p){ mySet.add§; } public synchronized boolean containsPerson(Person p){return mySet.contains§; }}别给我耍花样,我可看着你呢-java监视器我们的老熟人Vector和Hashtable都使用了java监视器模式,java监视器最大的优点就是简单,因为他不是什么强制性的要求,就跟起变量名称一样,只是一种约定,只要从头到尾只使用一种锁对象就可以保护对象的状态;//私有锁public class PrivateLock{ private final Object myLock=new Object(); @GuardedBy(“myLock”)Widget widget; void someMethod(){//访问或者是修改Widget的状态 synchronized(myLock){} }}私有锁的好处就是封装,也就是在自己的地盘上自己说了算,自己的同步策略就不会受到干扰了,当使用非线程安全对象组装一个类的时候java监视器模式非常好用;重要的事情交给专业的人-委托话不多说,先上代码,我就喜欢用代码来说话,这是一个单一线程安全的状态变量的例子;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值