インタビューで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 可観測性分散トレース

推薦する

企業ウェブサイトがランキング上位なのに利益が出ないというジレンマを打破する方法を分析

インターネットが急速に発展する中、企業がインターネット上で独自のチャネルを開設できなければ、このよう...

10月10日のBaiduのスナップショットがまたおかしいです。気づきましたか?これは何を示していますか?

今日、Baidu が小さなアップデートを行いました。アップデート後、データを整理してデータ分析を行い...

Oracle SaaSは中国市場をリードし続け、第1位に

「エコシステム全体の強化と新しいエクスペリエンスのインテリジェントな構築」をテーマにした 2017 ...

ユーザーのニーズを深く探り、価値の高い記事コンテンツをユーザーに提供する方法

周知のとおり、Baidu アルゴリズムのアップグレードにより、ユーザー エクスペリエンスは SEO ...

ネオサージ|1億2800万|xen|1兆|20米ドル/年

NeoSurge は、超割引の VPS モデル、neo-1 VPS を発売しました。価格は月額 1....

あなたのウェブサイトが含まれていない、心配ですか? Yunzhi のウェブサイト構築により、1 か月で Baidu のホームページに掲載されるようになります

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますウェブサイ...

中国のクラウドコンピューティング市場は1,000億米ドルに達するでしょう。

現在の企業 IT インフラストラクチャ技術の唯一の選択肢として、クラウド コンピューティングは探索と...

医療ウェブサイトのSEO: バレンタインデーに受けた思いがけないサプライズをシェアしましょう

医療ウェブサイトにとって、ユーザーエクスペリエンスは特に重要です。避けて通れない問題です。あらゆる分...

クラウドネイティブコンテナセキュリティプラクティス

概要:クラウド ネイティブは、一連の技術システムと方法論です。クラウド ネイティブは、クラウドとネイ...

SEO を利用してビジネスを始めて金持ちになりませんか?誰でもできるわけではない!

インターネットやニュースで、ウェブサイトを開設して月に数万元を稼いでいるという話をよく耳にするかもし...

タオバオストアの購買転換率に影響を与える致命的なポイント

少し前、多くの淘宝網の販売業者が張立氏を見つけ、自分の店舗の状況を調べるのを手伝ってほしいと頼んだ。...

推奨: budgetvm-$4.99/2IP/1g メモリ/75g SSD/3T トラフィック/Alipay/4 コンピュータ ルーム

budgetvmのSSDハードドライブVPSの価格が値下げされました。現在、1Gの価格は512Mメモ...

2345ナビゲーション海賊事件:会長と他の8人の被告に執行猶予付きの判決

IT Timesの記者は、情報筋から、2011年に公安部が実施した「抜刀作戦」における主要なソフトウ...

良いストーリーを伝えるにはどんなスキルが必要ですか?

最近、小説家という新しい勢力を紹介する非常に有名な公開アカウントを見ました。 WeChatの記事の最...