hi,你好!欢迎访问本站!登录
本站由简数采集腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 教程 - 杂谈 - 正文 君子好学,自强不息!

Java 并发编程(四):怎样保证对象的线程安全性

2019-11-18杂谈搜奇网39°c
A+ A-

本篇来谈谈 Java 并发编程:怎样保证对象的线程平安性。

01、媒介

先让我吐一句肺腑之言吧,不说出来会憋出内伤的。《Java 并发编程实战》这本书太特么死板了,只管它被奉为并发编程当中的经典之作,但我照样不由得。由于第四章“对象的组合”我整整啃了两周的时刻,才啃出来点肉丝。

读者朋友们包涵啊。要怪只能怪我自身的进修才能有限,真读不了这类僵硬无趣的手艺书。然则为了进修,为了提高,为了未来(标语喊得有点大了),只能硬着头皮上。

请随我来,我只管写得风趣点。

02、线程平安类

作者说了啊,设想一个线程平安类须要三个步骤:

1)找出示意对象状况的一切变量
2)对变量举行有用性束缚
3)增添类的并发接见战略

我在作者说的基础上做了微调,读起来越发轻易明白。怎样和代码对应起来了,先来看一个一般的计数器类 Counter。

public class Counter {
    private int value = 0;

    public int getValue() {
        return value;
    }

    public int increment() {
        return ++value;
    }
}

1)Counter 的状况变量只要一个,就是 value。

2)value 的有用性是什么呢,它最大不能超过 Integer.MAX_VALUE,最小只能为 0(计数嘛,总不能记成负数)。换句话说就是,value 的有用局限是 0 ~ Integer.MAX_VALUE

public int increment() {
    if (value == Integer.MAX_VALUE) {
        throw new IllegalStateException("counter overflow");
    }
    return ++value;
}

3)增添类的并发接见战略,直接上 synchronized。

public class Counter {
    private int value = 0;

    public synchronized int getValue() {
        return value;
    }

    public synchronized int increment() {
        if (value == Integer.MAX_VALUE) {
            throw new IllegalStateException("counter overflow");
        }
        return ++value;
    }
}

03、非线程平安的对象

之前我们谈了怎样设想一个线程平安的类。如果类是平安的,那末它作为对象运用的时刻就是线程平安的。但如果一个类不是线程平安的,它作为对象运用的时刻怎样保证是线程平安的呢?

作者提到了一个名词叫做“关闭机制”:

1)把对象作为类的私有成员变量;
2)把对象作为要领内部的局部变量;
3)线程 A 把对象通报到 B 线程,而不是与线程 B 同享这个对象;

人人来看下面这段代码。

class StringList {
    private List<String> myList = new ArrayList<>();
    
    public synchronized void addString(String s) {
        myList.add(s);
    }
    
    public synchronized void removeString(String s) {
        myList.remove(s);
    }
}

自身 ArrayList 不是线程平安的,但 myList 是私有的,接见它的两个要领 addString()removeString() 都加了关键字 synchronized,因而 myList 在运用的时刻就变成了线程平安的对象,StringList 类就变成了一个线程平安的类——这类体式格局被称作 Java 监视器形式:可变的状况被封装在一个类中,接见它们只能经由过程加上锁的要领。

检察 Vector 的源码,你会发明,它之所以是线程平安的,就是采纳的这类监视器形式

04、在已有的线程平安类上追加功用

如果如今有一个线程平安的类,比方之条件到的 StringList,它包含了大多数我们须要的功用,但还不够,那末怎样确保我们追加的功用不损坏原有的线程平安性呢?

最直接的要领固然是修正源码,如果源码控制在我们自身手里的话。

class StringList {
    private List<String> myList = new ArrayList<>();
    
    public synchronized void addString(String s) {
        myList.add(s);
    }
    
    public synchronized void addIfNotExist(String s) {
        boolean isExist = myList.contains(s);
        if (!isExist) {
            myList.add(s);
        }
    }
}

我们新增了一个 addIfNotExist() 要领:如果字符串 s 还没有增加到 List 当中,就增加一个。

新增的要领没有损坏 StringList 的线程平安性,由于当两个线程同时实行 addIfNotExist() 要领时,须要经由 synchronized 看守的这道大门。

但许多时刻,我们没法直接修正源码,这时刻就只幸亏本来的基础上举行革新。人人听过之前的“红芯”浏览器吗?在谷歌浏览器的内核上裹了一层层天子的新衣。

class StringList {
    protected List<String> myList = new ArrayList<>();
    
    public synchronized void addString(String s) {
        myList.add(s);
    }
}

public class NewStringList extends StringList {
    public synchronized void addIfNotExist(String s) {
        boolean isExist = myList.contains(s);
        if (!isExist) {
            myList.add(s);
        }
    }
}

新建一个类 NewStringList,继续自 StringList,然后在 NewStringList 中新增一个要领 addIfNotExist()。固然了,如许做的条件是父类中的 myList 是 protected 而不是 private 的。因而,这类做法不具有普适性。

05、末了

站在我的角度来看,《Java 并发编程实战》的第四章“对象的组合”写得烂透了。致使我在写这篇文章的时刻感觉到万分的痛楚。愿望下一章不要写的这么烂。

上一篇:怎样保证同享变量的可见性?

上上篇:怎样保证同享变量的原子性?

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  移步手机端
Java 并发编程(四):怎样保证对象的线程安全性

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
未定义标签

本文来源:搜奇网

本文地址:https://www.sou7.cn/282358.html

关注我们:微信搜索“搜奇网”添加我为好友

版权声明: 本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。请记住本站网址https://www.sou7.cn/搜奇网。

发表评论

选填

必填

必填

选填

请拖动滑块解锁
>>