[Java 并发] 并发编程实战笔记-对象的组合

编写线程安全的代码时,我们不希望对每次内存访问都进行分析一确保程序是线程安全的,而是希望将一些现有的安全组建组合为更大规模的组建或程序。下面介绍一些组合模式,这些模式能够使一个类更容易成为线程安全的,并且在维护这些类是不会无意中破坏类的安全性保证的。

设计线程安全的类

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

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

对象的状态是由对象的域组成的,有0-n个不等,如果域都是基本类型,那这些域构成对象的全部状态,如果有引用类型,那么该对象的状态包括被引用对象的域(如LinkedList的状态包括链表中所有节点对象的状态)。

实例封装

如果对象不是线程安全的额,那么可以通过多种技术使他在多线程程序中安全的使用。

  1. 可以确保该对象只能由单个线程访问(线程封闭),如JDBC Connection对对象,ThreadLocal。
  2. 通过一个锁来保护该对象的所有访问(Java监视器模式),如PersonSet,代码在后面。
  3. 封装对象,只暴露可访问的方法。与对象由整个程序访问的情况比,更容易对代码进行分析。如Collections中的UnmodifiableCollection。
// mySet不会逸出,唯一的外部引用就是PersonSet,使用Java监视器来封装能确保线程安全。
@ThreadSafe
    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);
        }
    }

将数据封装在对象内部,可以将数据的访问限制在对象的方法上,从而更容易确保线程的访问数据室总能持有正确的锁。

线程安全性的委托

我们可以把线程安全委托给先有的线程安全类,这样我们的代码阿九不用关心线程安全的问题了额。这里有两种情况:

  1. 如果委托给单独的线程安全类,能保证线程安全。如,我们可以使用ConcurrentHashMap保存线程共享数据。
  2. 如果委托给两个或两个已上的线程安全类,如果存在竞态条件,需要额外的同步机制保证;如果分别表示独立的状态,可以不使用额外的同步机制即可保证线程安全。
  3. 在现有线程安全类中添加功能,叫作客户端加锁。这种机制是派生类的行为与基类耦合在一起,破坏了基类的同步策略,使用时需要特别小心

示例代码:

// 情况2,需要增加同步机制保证 check-than-act
public class NumberRange {
    // INVARIANT: lower <= upper
    private final AtomicInteger lower = new AtomicInteger(0);
    private final AtomicInteger upper = new AtomicInteger(0);
    public void setLower(int i) {
        // Warning -- unsafe check-then-act , need a lock
        if (i > upper.get())
            throw new IllegalArgumentException(
                    "can't set lower to " + i + " > upper");
        lower.set(i);
    }
    public void setUpper(int i) {
        // Warning -- unsafe check-then-act , need a lock
        if (i < lower.get())
            throw new IllegalArgumentException(
                    "can't set upper to " + i + " < lower");
        upper.set(i);
    }
    public boolean isInRange(int i) {
        return (i >= lower.get() && i <= upper.get());
    }
}

小结

这一章介绍了实现线程安全类是采用的一些技术。

  1. 线程安全可以委托给现有的线程安全类。
  2. 委托是创建线程安全的一个有效策略。
  3. 值需要让现有的线程安全类管理所有的状态即可
  4. 当需要使用多个线程安全类保存状态是,需要额外的同步机制保证。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • layout: posttitle: 《Java并发编程的艺术》笔记categories: Javaexcerpt...
    xiaogmail阅读 5,787评论 1 19
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,169评论 11 349
  • 今天晚上和老二去接姐姐的路上,宝贝问:妈妈你看到QQ上老师发的视频了?”我说:“没看啊,今天妈妈去商场了,...
    孙若菡妈妈阅读 215评论 0 0
  • “一个人说正经话,说得不对可以劝他;一个人在胡言乱语,何劝之有?” 因都不爱说话,两人倒能说到一起。 是让小谢明白...
    Wisconsin0607阅读 320评论 0 0