インタビューでCopyOnWriteに答える3つのレベル、最後のレベルに答えられるのは1%の人

インタビューでCopyOnWriteに答える3つのレベル、最後のレベルに答えられるのは1%の人


今日は、非常にハードコアな技術的知識についてお話ししましょう。 CopyOnWrite のアイデアと、Java 並行性パッケージにおけるその具体的な表現を分析します。これには、このアイデアが Kafka カーネル ソース コードで並行性パフォーマンスを最適化するためにどのように使用されているかも含まれます。

この CopyOnWrite は、面接官が面接中に候補者を一撃で仕留める必殺武器になる可能性があります。それは候補者がオファーを得るための秘訣になるかもしれません。それは比較的高度な知識です。

1. 読書が増え、執筆が減るシナリオによって生じる問題は何ですか?

これで、メモリ内に ArrayList が存在することが想像できます。この ArrayList は、デフォルトでは間違いなくスレッドセーフではありません。複数のスレッドがこの ArrayList を同時に読み書きすると、問題が発生する可能性があります。

さて、ここでの疑問は、この ArrayList をスレッドセーフにするにはどうすればいいかということです。

この ArrayList へのすべてのアクセスにスレッド同期制御を追加する非常に簡単な方法があります。

たとえば、この ArrayList には同期されたコード セグメントでアクセスして、1 つのスレッドが同時に操作できるようにしたり、ReadWriteLock を使用して制御したりする必要があります。

この ArrayList へのアクセスを制御するために、ReadWriteLock 読み取り/書き込みロックを使用していると想定します。

この方法では、ArrayList からデータを読み取るために複数の読み取り要求を同時に実行できますが、読み取り要求と書き込み要求は相互に排他的であり、書き込み要求と書き込み要求も相互に排他的です。

見てみましょう。コードはおそらく次のようになります。

 パブリックオブジェクト読み取り(){
lock.readLock () を実行します。 ロック() ;
// ArrayList から読み込む
ロックを解除します ロックを解除します();
}
パブリックボイド書き込み(){
lock.writeLock () を実行します。 ロック() ;
// ArrayListに書き込む
ロック.writeLock () ロックを解除します();
}

考えてみてください。上記のコードのどこが間違っているのでしょうか?

実際のところ、最大の問題は書き込みロックと読み取りロックの相互排他性にあります。書き込み操作の頻度が非常に低く、読み取り操作の頻度が非常に高い、つまり書き込みよりも読み取りが多いシナリオを想定します。

では、書き込み操作が時々実行される場合、書き込みロックが追加されるのでしょうか?このとき、大量の読み取り操作がブロックされ、実行できなくなりますか?

これは、読み取り/書き込みロックが遭遇する可能性のある最大の問題です。

2. 問題を解決するためにCopyOnWriteのアイデアを導入する

この時点で、問題を解決するには CopyOnWrite の考え方を導入する必要があります。

彼の考えは、読み取り/書き込みロックを追加する必要はなく、すべてのロックを削除するだけでよいというものです。ロックは問題を引き起こし、相互排他を引き起こし、パフォーマンスの低下につながる可能性があります。私のリクエストをブロックしたため、リクエストが停止し、実行できなくなりました。

それで、マルチスレッド同時実行のセキュリティをどのように確保するのでしょうか?

とても簡単です。名前が示すように、「CopyOnWrite」方式を使用します。英語から中国語に翻訳すると、おおよそ「データを書き込むときにコピーを使用して実行する」という意味になります。

データを読み取るときは、ロックしなくても問題ありません。誰もがそれを読んでいるだけなので、お互いに影響を与えません。

主な問題は、書くときです。書き込み時にロックできないため、戦略を採用する必要があります。

ArrayList がリスト データを格納するための配列に基づいている場合、配列内のデータを変更するには、まず配列のコピーを作成する必要があります。

次に、変更するデータを配列のコピーに書き込むことができますが、このプロセスでは実際にはコピーに対して操作を行っています。

この場合、読み取り操作も同時に正常に実行できますか?この書き込み操作は読み取り操作には影響しません。

このプロセスを体験するには、以下の画像をご覧ください。

ここで重要な疑問は、書き込みスレッドがコピー配列を変更した後、読み取りスレッドはこの変更をどのように認識できるかということです。

ここが重要なポイントです。注目してください。ここでは volatile キーワードを使用する必要があります。

以前、 volatile キーワードの使用法を説明する記事を書きました。中心となるのは、書き込みスレッドによって変数が変更された直後に、他のスレッドが変数によって参照される最新の値を読み取れるようにすることです。これが volatile のコア機能です。

したがって、書き込みスレッドがコピー配列の変更を完了すると、揮発性書き込みを使用して、コピー配列を揮発性で変更された配列の参照変数に割り当てることができます。

揮発性変数に値が割り当てられるとすぐに、その値は読み取りスレッドにすぐに表示され、誰もが最新の配列を見ることができます。

以下は、JDK の CopyOnWriteArrayList のソース コードです。

データの書き込み時に配列をコピーし、そのコピーを変更し、揮発性変数を割り当てることで変更された配列のコピーを更新し、他のスレッドにすぐに表示できるようにする方法を見てみましょう。​

 // この配列は volatile で変更されているためコアです
// 最新の配列が割り当てられている限り、他のスレッドは最新の配列をすぐに見ることができます
プライベート一時的な揮発性オブジェクト[] 配列;
パブリックブール値add ( E e ) {
最終的なReentrantLock ロック= thisロック;
ロックロック();
試す{
オブジェクト[] elements = getArray ();
int len ​​= 要素長さ;
// 配列のコピーを作成する
オブジェクト[] newElements = 配列copyOf ( 要素長さ+ 1 );
// コピー配列に要素を追加するなどして変更する
新しい要素[ 長さ] = e ;
// 次にコピー配列を揮発性の変更された変数に割り当てます
setArray ( 新しい要素);
true を返します
ついに
ロックロックを解除します();
}
}

そこで、更新はコピーを通じて行われるので、複数のスレッドを同時に更新する必要がある場合はどうなるのかと誰もが考えました。複数コピーしても問題ないでしょうか?

もちろん、複数のスレッドを同時に更新することはできません。このとき、上記のソース コードを見ると、ロック メカニズムが追加されており、同時に更新できるスレッドは 1 つだけであることがわかります。

では、更新すると読み取り操作に何らかの影響があるのでしょうか?

絶対にそうではありません。読み取り操作は単なる配列の読み取りであり、ロックは発生しません。そして、volatile で変更された変数の割り当てを更新している限り、読み取りスレッドは最新の変更された配列をすぐに確認でき、これは volatile によって保証されます。​

 プライベートE get ( オブジェクト[] aint インデックス) {
// 配列を読む最も簡単な方法
( E ) a [ インデックス] を返します
}

これにより、先ほど述べた「読む量が増え、書く量が減る」という問題が完璧に解決されます。

読み取り/書き込みロックを相互排他に使用すると、書き込みロックによって多数の読み取り操作がブロックされ、同時実行パフォーマンスに影響します。

ただし、CopyOnWriteArrayList を使用すると、スペースと引き換えに時間がかかります。更新時はロックを回避するためにコピーを元に更新し、最後に揮発性変数を使用して値を割り当てて可視性を確保します。このアップデートは読書スレッドには影響しません。

3. Kafka ソースコードでの CopyOnWrite の考え方の適用

Kafka のカーネル ソース コードには、クライアントが Kafka にデータを書き込むときに、最初にクライアントのローカル メモリ バッファーにメッセージを書き込み、次にメモリ バッファー内でバッチを形成して Kafka サーバーに一度に送信し、スループットを向上させるというシナリオがあります。

では、早速次の画像を見てみましょう。

現時点で Kafka のメモリ バッファーはどのようなデータ構造を使用していますか?ソースコードを見てみましょう:

 プライベート最終ConcurrentMap < topicpartitiondeque <= "" span = "" >
バッチ= 新しいCopyOnWriteMap < TopicPartitionDeque > ();

このデータ構造は、メモリ バッファーに書き込まれたメッセージを格納するために使用されるコア データ構造です。このデータ構造を理解するには、Kafka カーネル ソース コードの多くの概念を説明する必要がありますが、ここでは詳しく説明しません。

しかし、誰もが1つの点に注意する必要があります。彼は自分で CopyOnWriteMap を実装しており、この CopyOnWriteMap は CopyOnWrite の考え方を採用しています。

CopyOnWriteMap のソース コード実装を見てみましょう。

 // 通常の Map の典型的な volatile 変更
プライベートvolatile Mapmap ;
@オーバーライド
パブリック同期V put ( K kV v ) {
// 更新するときは、まずコピーを作成し、コピーを更新してから、揮発性変数の値を書き戻します
Mapcopy = new HashMap ( this . map );
V = コピー。 ( k , v ) を置く
これmap = コレクション変更不可能なマップ ( コピー);
を返す;
}
@オーバーライド
パブリックV get ( オブジェクトk ) {
// 読み取り時に、揮発性変数によって参照されるマップデータ構造をロックせずに直接読み取ります
マップを返します取得( k );
}

したがって、Kafka のコア データ構造が CopyOnWriteMap の考え方を使用して実装されている理由は、この Map のキーと値のペアがそれほど頻繁に更新されないためです。

つまり、TopicPartition-Deque のキーと値のペアの更新頻度は非常に低くなります。

ただし、その get 操作は、キューのエンキューやデキューなどの操作を実行するために、TopicPartition に対応する Deque データ構造を高頻度で読み出すため、高頻度読み取り要求となります。したがって、このマップの場合、高頻度操作は get 操作になります。

現時点では、Kafka は CopyOnWrite の考え方を採用してこの Map を実装し、キー値の更新時に高頻度の読み取り操作がブロックされるのを回避し、ロックフリー効果を実現し、スレッドの同時実行パフォーマンスを最適化します。

この記事を読めば、CopyOnWrite の概念と、JDK での実装や Kafka ソース コードでのアプリケーションなど、適用可能なシナリオについて理解が深まると思います。

面接中にこのアイデアと JDK でのその具体化を明確に説明でき、さらに有名なオープンソース プロジェクト Kafka の基礎となるソース コードと組み合わせて面接官に説明できれば、面接官は間違いなくあなたに対してより良い印象を持つでしょう。

<<:  2022年グローバルハイブリッドクラウド開発トレンドレポート

>>:  Dapr 可観測性分散トレース

推薦する

Hongmeng HarmonyOSコンポーネントの分散適応とアプリケーションビジョン

[[377205]]詳細については、以下をご覧ください。 51CTOとHuaweiが共同で構築したH...

オンラインマーケティングとポーカー

オンラインプロモーションとカードゲームは、私が毎日行っていることです。まずはカードについてお話ししま...

事例分析:2つの小さな機能が新たなマーケティングをもたらす

黄家朗著WeChat は多くの小さな機能を備えたソーシャル ツールです。実際、これらの小さな機能をう...

ゴールドマン・サックス:オラクルは敗者

ゴールドマン・サックスの最新の支出報告では、オラクルは敗者の1社となった。このレポートでは、複数の企...

海底濠の堀と新しい配置

創業30年近い海底撈は、多角化戦略を活用して第2の成長曲線を切り開いている。昨夜、海底撈は中間業績報...

企業向けオンラインニュースマーケティングの7つのメリット

ニュース マーケティングとは、その名の通り、企業のマーケティング情報をニュースの形でメディアを通じて...

クラウドコンピューティングの人工知能の開発は遅いが、注目を集めている。

IT プロフェッショナルが AI の適用を実験する際、その多くはパブリック クラウドでそれを実行する...

香港のShuhost特別プロモーションサーバーの簡単なレビュー

Shuhost Technologyの香港データセンターでは、イベント向けのプロモーションモデルが頻...

なぜ私はBaiduに問題があるのか​​ルールは無料の価値を強調する

私のブログが百度のウェブ検索に侵害されたため、この2日間、百度との交渉のための法的文書の作成に取り組...

百度と中国の検索:検索の科学と芸術を学ぶ人々

10年前、私はインターネット製品を作り、それが成功しました。同様のインターネット製品は 10 年後に...

人材ネットワーク運営の費用を人材紹介会社に支払わせる方法

人材ネットワークの運営には、求職者と人材紹介会社の2つの主な利用者が存在します。オフラインのエージェ...

3分レビュー! 2021年7月のクラウドコンピューティング分野の重要な動向を簡単に紹介します

2020年以降、クラウドコンピューティングがトレンドになりました。ますます多くの資本と企業がクラウド...

Google検索エンジンとの互換性が高いウェブサイトを作成する

Google が 2010 年 3 月 23 日 0:00 に中国本土市場から正式に撤退して以来、中...

ウェブサイトのコンテンツをうまく作るには、10のポイントから始める必要があります

ウェブサイトの重さはウェブサイトのコンテンツに直接左右されることを認めなければなりません。ウェブサイ...

ユーザーエクスペリエンスを向上させ、SEOに役立つ5つの必須WordPressプラグイン

SEO 担当者にとって、個人ブログは不可欠です。なぜなら、ブログは SEO 作業を支援し、SEO の...