设计线程安全的类

设计线程安全的类:

在设计线程安全类的过程中,需要包含以下三个基本要素:

  • 找出构成对象状态的所有变量;
  • 找出约束状态变量的不变性条件;
  • 建立对象状态的并发访问管理策略。

要分析对象的状态,首先从对象的域开始。如果对象中所有的域都是基本类型的变量,那么这些域将构成对象的全部状态。如果对象的域中引用了其他对象,则该对象的域包含被引用对象的域。

同步策略定义了如何在不违背对象的不变性条件和后验条件的情况下对其状态的访问操作进行协同。同步策略规定了如何将不可变性、线程封闭与加锁机制等结合起来以维护线程的安全性,并且还规定了哪些变量由哪些锁来保护。

收集同步需求:

在许多类中都定义了一些不可变条件,用来判断状态是有效的还是无效的。例如long类型的变量,其状态空间是Long.MIN_VALUE到Long.MAX_VALUE。但我们定义了一个类,该类中有一个long类型的计数器,则该long类型的变量存在一个限制,即不能为负值。

同样,在操作中还会包含一些后验条件来判断状态迁移是否是有效的。如计数器当前值为17,那么下一状态只能是16或18.当下一个状态需要依赖当前状态时,这个操作就必须是一个复合操作。

由于不变性条件和后验条件在状态和状态转换上添加了与许多限制,因此就需要额外的同步和封装。

如果不了解对象的不可变条件和后验条件,那么就不能确保线程安全性。要满足各种约束条件,就需要借助于原子性与封装性。

依赖状态的操作:

类的不变性条件和后验条件约束了在对象上有哪些状态和状态转换是有效的。在某些对象的方法中还包含一些基于状态的先验条件。例如不能从空队列中删除一个元素。如果在某个操作中包含有基于状态的先验条件,那么这个操作就被称为依赖状态的操作。

线程安全性委托:

大多数对象都是组合对象。当从头开始构建一个类或者将多个非线程安全的类组合成一个类时,监视器模式非常有用。但如果类中各个组件已经是线程安全的,会是什么情况?在某些情况下通过多个线程安全类组合而成的类是线程安全的,而在某些情况下不是。

如果某个类含有复合操作,那么仅靠委托并不足以实现线程安全性。在这种情况下这个类必须提供自己的加锁机制以保证这些复合操作都是原子操作,除非整个复合操作都可以委托给状态变量。

如果一个类是由多个独立且线程安全的状态变量组成,并且在所有的操作中都不包含无效的状态转换,那么可以将线程安全性委托给低层的状态变量。

发布低层的状态变量:

当把线程安全性委托给某个对象的底层状态变量时,什么条件下可以发布这些变量从而使其他类可以修改它们?答案仍然取决于在类中对这些变量施加了什么不变性条件。

如果一个状态变量是线程安全的,并且没有任何不变性条件来约束它的值,在变量的操作上也不存在任何不允许的状态转换,那么就可以安全地发布这个变量。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏瓜大三哥

Verilog 模块编程要点

1) 时序电路建模时,用非阻塞赋值。 2) 锁存器电路建模时,用非阻塞赋值。 3) 用 always 块建立组合逻辑模型时,用阻塞赋值。 4) 在同一个 alw...

22160
来自专栏Echo is learning

R 数据分析

29420
来自专栏架构说

缓存策略之LRU实现及分析

LRU定义 Cache的容量有限,因此当Cache的容量用完后,而又有新的内容需要添加进来时, 就需要挑选并舍弃原有的部分内容,从而腾出空间...

347100
来自专栏用户2442861的专栏

网易2013校园招聘笔试题详解

http://blog.csdn.net/silangquan/article/details/18142651

15320
来自专栏Python疯子

Objective-C语法基础之Category的使用

Category:扩展类或分类 无论一个类设计的如何完美,都不可避免的会遇到没有预测到的需求,那怎么扩展现有的类呢?当然,继承是个不错的选择。但是Object...

9520
来自专栏coder修行路

Nginx location 匹配顺序整理

Nginx location模块整理 具体的Nginx安装就不在这里描述了,这里只是为了对location的描述 Nginx环境 a. 查看当前系统cat /e...

35270
来自专栏前端杂货铺

深入seajs源码系列三

入口方法        每个程序都有个入口方法,类似于c的main函数,seajs也不例外。系列一的demo在首页使用了seajs.use(),这便是入口方法。...

28760
来自专栏海天一树

小朋友学C语言(42):gets和fgets

这里可以看出来,定义了s的长度为3,但是用gets()输入字符串的时候,并不会去检查字符串的长度,所以导致char的值不是a,而是”uvwxyz”中的第四个字符...

18810
来自专栏Java面试笔试题

简述synchronized 和java.util.concurrent.locks.Lock的异同?

Lock是Java 5以后引入的新的API,和关键字synchronized相比主要相同点:Lock 能完成synchronized所实现的所有功能;主要不同点...

14840
来自专栏大内老A

ASP.NET MVC的Model元数据提供机制的实现

在前面的介绍中我们已经提到过表示Model元数据的ModelMetadata对象最终是通过一个名为ModelMetadataProvider的组件提供的,接下来...

22660

扫码关注云+社区

领取腾讯云代金券