プログラマは:どのように同時の安全を保証するために、変数を共有し、ロックしませんか?!

このブログの猫おじさんのブログは、再現、ソースを明記してください

「15分」については、この記事を読みます

フィットネス群衆を読む:Javaの中級

研究ノート、残りの2日間は、(実際には、シミュレーションプロジェクトの戦闘期間をやって)、そして時折、彼らが何をすべきかを考え、自分自身または行う社会に本当に意味がありますか?

画像
ビジュアル狩りの写真

あなたの答えを話します

emmm、複数の回答、今日は簡単にご紹介します

質問読む:オーバーヘッドを回避しながら、どのように我々は、スレッドセーフの共有変数へのアクセスを保証しないことは、それを生成するためにロックを導入しました

並行環境で、容易にデータの一貫性のために、次に、複数のスレッドで共有することができる被験体は、必要とされます

あなたは、明示的なロックやCAS操作を使用することができますが、それはまた、コンテキストスイッチのオーバーヘッドの一部をもたらすでしょう、などが、

今現在の問題の例を与えるために、

/**
 * @ClassName Cup
 * @Description 杯子 非线程安全
 * @Author MySelf
 * @Date 2019/9/25 21:28
 * @Version 1.0
 **/
public class Cup {

    //直径
    private double diameter;

    //高度
    private double height;

    public double getDiameter() {
        return diameter;
    }

    public double getHeight() {
        return height;
    }

    //非原子操作
    public void setCup(double diameter,double height){
        this.diameter = diameter;
        this.height = height;
    }
}
复制代码

上記のコードは、我々は、非スレッドセーフ右(あなたが見ることができない場合は、検討中の記事をオン)を見ることができるはずです

我々はsetCup操作の直径を割り当てられたときに、別のスレッドが彼の高さを読み始めたかもしれないので、それはスレッド安全性の問題になります。

だから、ロックを使用せずに、どのように行うことができますか?

ダウン聖歌見て、ほとんどの友人の輪を磨くための時間、急に理解することが良いです

不変オブジェクト

はい、今日はカップを話すための方法は、不変オブジェクトになると言いました!

不変オブジェクト:オブジェクトが作成されると、その外部の可視状態は変わらない(類似文字列、整数)

そして、カップの上にそれを変更する方法する必要がありますか?

/**
 * @ClassName Cup
 * @Description 不可变对象,线程安全
 * @Author MySelf
 * @Date 2019/9/25 21:32
 * @Version 1.0
 **/
public final class Cup {

    private final double diameter;

    private final double height;

    public Cup(double diameter,double height){
        this.diameter = diameter;
        this.height = height;
    }

}
复制代码

この時間ではないJiuhaolaは変更されません

待って、私はカップああを変更する方法にしたいですか?でも同時動作、私のビジネスにもああ、このカップを変更する必要があります

プロパティを変更し、のは、視野を調節してみましょう==交換カップインスタンスカップ

私たちは、カップの金型工場ます最近のネット赤いカップを生成しているが、理由印象のインターネットの傾向ということ、そして時折小さな変更に必要があると私たちのこのカップパラメータ、5本のライン上のアダプタの金型にお金を失うことになる生産なので、コードを停止彼ら属性カップは不変オブジェクトの場合に置き換えることができます

/**
 * @ClassName MoldAdapter
 * @Description 模具适配器
 * @Author MySelf
 * @Date 2019/9/25 21:35
 * @Version 1.0
 **/
public class MoldAdapter {
    
    private Map<String,Cup> cupMap = new ConcurrentHashMap<String, Cup>();

    public void updateCup(String version,Cup newCup){
        cupMap.put(version, newCup);
    }

}
复制代码

ConcurrentHashMapの交換が関連していない、ロックの内側にここにかかわる、カップと新しいデモ、プロセスがロックを含みません

おそらく、クレーン機械ケースについてのいくつかの漠然とした話で?

私の青春クレーン機械の破滅を覚えていますか?

私は、あなたが彼女はその1、その結果をキャッチしたかったことを自慢することができます長い時間前に、彼の妻は、まだバブルだった人形で遊ぶために彼女を取ったときに覚えている?????

画像

それは呼ばれています50

今では、私たち自身の主人スタンドアップするターン、およびハムです

、私たちは人形の頭部エリア・マシン、それに対応する機械の番号を持っている各クレーンマシンですと仮定し、二次元コードのURL、ロボット周波数(右、非専門家の機械労働者を支払う、これはお金を稼ぐためにあると仮定することがここにあります)焦点を当て、私たちは、ショートパンツはお金にはまっ若者、リストに一度、生命など、毎晩の清算が進行していることを前提としています。

最近のナショナルデーの間に来る観光客の数と一致している????

挿入し、ここに猫[Javaは]事前に公衆数は、私は繁栄、平和と繁栄の70周年を望むと述べました!

お金のアイデアを作りたい、曹操は胸にジャンプしました

周波数のロボットクレーンマシンだから、良い手段

私はしかし、私は人形を持つマシンをコーディングの関係マップを持って始めた、クレーン機械のターゲット部分のプロパティを変更する必要があります

私は行くためにお金を稼ぐために彼らのビジネスに導入するアイデアの対象になりません。

不変オブジェクトになり、オブジェクトのようにまず、クレーン機

/**
 * @ClassName DollMachineInfo
 * @Description 娃娃机不可变对象
 * @Author MySelf
 * @Date 2019/9/25 21:51
 * @Version 1.0
 **/
public final class DollMachineInfo {

    //编号
    private final String number;

    //支付二维码url
    private final String url;

    //机械手频率
    private final int frequency;

    public DollMachineInfo(String number,String url,int frequency){
        this.number = number;
        this.url = url;
        this.frequency = frequency;
    }

    public DollMachineInfo(DollMachineInfo dollMachineInfoType){
        this.number = dollMachineInfoType.number;
        this.url = dollMachineInfoType.url;
        this.frequency = dollMachineInfoType.frequency;
    }

    public String getNumber() {
        return number;
    }

    public String getUrl() {
        return url;
    }

    public int getFrequency() {
        return frequency;
    }
}
复制代码

私はエンコードのマシンと人形・リレーショナル・マッピングテーブルを変更する必要があるので、テーブルも不変である必要があり、この時間は、彼は私がリレーショナルマッピングテーブルを取得サポートを必要とし、最新のリレーショナルマッピングコンテンツを交換する必要性

/**
 * @ClassName MachineRouter
 * @Description 机器信息表
 * @Author MySelf
 * @Date 2019/9/25 21:57
 * @Version 1.0
 **/
public final class MachineRouter {
    //保证其在并发环境的内存可见性
    private static volatile MachineRouter instance = new MachineRouter();
    //code与机器之间的映射关系
    private final Map<String,DollMachineInfo> routeMap;

    // 2、存储不可变量routeMap
    public MachineRouter(){
        //将数据库表中的数据加载到内存,存为Map
        this.routeMap = MachineRouter.setRouteFromeDB();
    }

    // 3、从db将数据存入Map
    private static Map<String, DollMachineInfo> setRouteFromeDB(){
        Map<String, DollMachineInfo> map = new HashMap<String, DollMachineInfo>();
        //DB 代码
        return map;
    }

    // 1、初始化实例
    public static MachineRouter getInstance(){
        return instance;
    }

    /**
     * 根据code获取对应的机器信息
     * @param code 对应编码
     * @return 机器信息
     */
    public DollMachineInfo getMacheine(String code){
        return routeMap.get(code);
    }

    /**
     * 修改当前MachineRouter实例
     * @param newInstance 新的实例
     */
    public static void setInstance(MachineRouter newInstance){
        instance = newInstance;
    }


    private static Map<String, DollMachineInfo> deepCopy(Map<String,DollMachineInfo> d){
        Map<String, DollMachineInfo> result = new HashMap<String, DollMachineInfo>();
        for (String key : d.keySet()){
            result.put(key, new DollMachineInfo(d.get(key)));
        }
        return result;
    }


    public Map<String, DollMachineInfo> getRouteMap() {
        //防御性复制
        return Collections.unmodifiableMap(deepCopy(routeMap));
    }
}
复制代码

次のステップは、同時ビジネス更新コードを追加することです

/**
 * @ClassName Worker
 * @Description 通讯对接类
 * @Author MySelf
 * @Date 2019/9/25 22:13
 * @Version 1.0
 **/
public class Worker extends Thread {

    @Override
    public void run(){
        boolean isRouterModification = false;
        String updateMachineInfo = null;
        while (true){
            //其余业务代码
            /**
             * 在通讯的Socket信息中解析,并更新数据表信息,再重置MachineRouter实例
             */
            if (isRouterModification){
                if ("DollMachineInfo".equals(updateMachineInfo)){
                    MachineRouter.setInstance(new MachineRouter());
                }
            }
            //其余业务代码
        }
    }

}
复制代码

黒板ノートをノック

ケースが終了し、基本的な概念があり、その後、専門用語を言います

それは不変オブジェクトモデル、不変オブジェクトであります

厳密に満たす必要があるどのような条件、不変オブジェクトを話します。

  • 1、クラス自体はfianl:防止のサブクラスは、行動の定義を変更します
  • fianl修正と2、すべてのフィールド:マルチスレッドであり、初期化することができますが、参照されたオブジェクトの安全なJMM場を確保するように変更され
  • オブジェクトが作成されると3、このキーワードは、他のクラスに与えられていません
  • 図4に示すように、可変オブジェクト(配列、コレクション)の他の引用された状態が、プライベートでなければならない外部に露出していない場合、フィールドを返す必要があり、防御複製(コピー防御)

不変オブジェクトモードを使用すると、同じについて知っておくべき二つの重要なものを持ってい

ImmutableObject:不変の状態の集合を格納するための責任

  • getStateを*:コンストラクタのインスタンスに引数によって得られた値、保持関連する変数の値を返しImmutableObject
  • getStateSnapshot:メンテナンスImmutableObject状態のスナップショットの配列を返します。

マニピュレータ:変更ImmutableObjectのメンテナンス、およびニーズが変化したとき、あなたはImmutableObjectの新しいインスタンスを生成に関与しています

  • changeStateTo:ImmutableObject値が新しい状態に応じて新しいインスタンスを生成します

典型的な相互作用のシナリオ

  • 1は、それぞれの状態は、現在の値を取得ImmutableObject
  • 図2に示すように、アプリケーション状態マニピュレータを更新するchangeStateToメソッドを呼び出し
  • 図3は、changeStateToは新しい状態を反映するようにImmutableObjectの新しいインスタンスを作成し、戻ります
  • 4、新ImmutableObjectの状態のスナップショットを取得

使用するためにどのようなシーン

はい、彼は私たちのタイトルの要件を満たしていたが、設計のあらゆる種類のは、その適切なシーンモードを持っています

一般的に、より適しました:

  • オブジェクトが頻繁に変更されません(人形のマシンの場合)
  • 同時に、原子性を確保するために設定されたデータを書き込む(ケースカップ)
  • キーのHashMapのようにオブジェクトを使用します(オブジェクトのハッシュコードを注意してください)

注意点:

  • オブジェクトの変更が頻繁に:CPUの消費を引き起こす可能性があり、GCは負担になります
  • 守備複製:回避外部コードは、その内部状態を変更します

プロフェッショナルケース

マルチスレッド環境でのセットは、多くの場合、コレクションの内部構造のトラバーサルを防ぐために、ロックに導入されたトラバース変更されました

ImmutableObjectモードの使用上のjava.util.concurrent.CopyOnWriteArrayList

もちろん、我々は、彼らがシーンに変更されているよりも頻繁に通過する、シーンを必要とします

その内部配列変数がコレクションを格納するために使用されて維持、あなたが要素を追加するとき、それは、新しい配列を生成する新しい配列に要素のセットをコピーして、要素を追加するための最後の要素、および新しい配列にコピーします配列、すなわち、配列が参照配列ImmutableObjectと同等であってもよい、音符が同等です

CopyOnWriteArrayListとを横断するときしたがって、ロックせずに、アレイイテレータ例の直接例を生成します

エピローグ

最終CopyOnWriteArrayListと私はソースコードで深刻な表情を持っていないので、細心の発言を開始していないので、主に私たちは不変オブジェクトモデルを理解することができ、それは、書き込みは、私たちが本番環境でこのアイデアを使用することができますことを願っていますし、デモを書き出すのが最善です貧しい人々、私を許して。

私自身は、まだ関連の知識と学習技術のプロダクトマネージャーに準拠し、私はこれがあなたに新しい知識を持って来ることを願って。

公開番号:Javaの猫が言いました。

学習交換基:728 698 035

今アーキテクチャ(コード農家)とビジネステクノロジーコンサルタント、平凡な奔放、オープンソース、生活や予定外のドライトーク番組が大好きです。

イメージテキスト

おすすめ

転載: juejin.im/post/5d8c10e8e51d45783e4b673e