Clojure にはロックレスの同時実行性があり、これは重要であると言われています。
私は多くの言語を使用してきましたが、それらが舞台裏でロックを実行していることに気づきませんでした。
Clojure (またはこの機能を持つ言語) でこれが利点になるのはなぜですか?
Clojure にはロックレスの同時実行性があり、これは重要であると言われています。
私は多くの言語を使用してきましたが、それらが舞台裏でロックを実行していることに気づきませんでした。
Clojure (またはこの機能を持つ言語) でこれが利点になるのはなぜですか?
ロックレス同時実行には、リーダーが他のリーダーを待つ必要がないという優れた利点もあります。これは、多くのスレッドが 1 つのソースからデータを読み取る場合に特に便利です。プログラムでデータの依存関係を定義し、安全に交換できるトランザクションの部分を明示的に定義する必要があります。
STM は、デッドロックやほとんどすべてのライブロックの発生からあなたを救いますが、同時実行の失敗からは救われません。履歴を維持するためのリソースが不足しているため、トランザクションが失敗するケースを作成することはできますが、重要な部分は、同時実行の失敗が明示的であることです。そしてあなたはそれらから回復することができます
Clojure について具体的に話すことはできませんが、仕事に取り掛かる前に誰かが何かを完了するのを待つ必要がないということです。これは素晴らしいことです。
通常、これは不変型で実現されます。何も変更できない場合は、他の誰かが変更を完了するまで待つ必要はありません。
デッドロック。または、より正確には、それらの欠如です。
ほとんどの言語における最大の問題の 1 つは、次のようなデッドロックが発生することです。
ロックがないので、明らかにデッドロックに陥ることはありません。
最大の問題は、ロックが構成しないことです。
単純なロック戦略でコードを書くのは簡単ですが (たとえば、同期された Java クラスにコードを配置するなど)、複数のオブジェクトをロックし始め、さまざまなロックされたオブジェクトを組み合わせた複雑なトランザクションを作成し始めると、指数関数的に複雑になります。オペレーション。デッドロックが発生し、パフォーマンスが低下し、ロック ロジックによってコードが非常に複雑になり、ある時点でコードが保守できなくなります。
これらの問題は、大規模で複雑な並行システムを構築しなければならない人なら誰でも明らかになるでしょう (そして、リッチ・ヒッキーが Clojure を作成する主な動機は、これらの問題を解決することでした)。
2 つ目の問題はパフォーマンスです。
ロックと STM はどちらも明らかにオーバーヘッドを課します。しかし、いくつかの重要なケースでは、STM のオーバーヘッドが大幅に削減されることがあります。
特に、(Clojure STM と同様に) ロックレス同時実行は、通常、リーダーがトランザクションの外部のデータにアクセスする場合、他のスレッド (ライターを含む!) によって損なわれないことを意味します。これは、読み取りがトランザクションである必要がなく、書き込みの数を劇的に上回るというかなり一般的なケースでは大きなメリットとなります (ほとんどの Web アプリケーションを考えてみてください...)。Clojure での STM 参照の非トランザクション読み取りは、本質的にオーバーヘッドがありません。
厳密にシーケンシャルなプログラム (A、B、C の順に行う) を作成している限り、同時実行性の問題はなく、言語の同時実行メカニズムは関係ありません。
「プログラミング演習」プログラムを卒業して現実世界のものに移行すると、すぐにマルチスレッド (または利用可能な並行処理のフレーバー) が解決策となる問題に遭遇します。
ケース: GUI を使用するプログラム。スペル チェック機能を備えたエディターを作成しているとします。スペル チェッカーをバックグラウンドで静かに処理しつつ、GUI がユーザー入力をスムーズに受け入れるようにしたいと考えています。したがって、これら 2 つのアクティビティを個別のスレッドとして実行します。
ケース: 最近、2 つのログ ファイルから統計情報を収集してデータベースに書き込むプログラムを (仕事用に) 作成しました。各ファイルの処理には約 3 分かかります。これらのプロセスを並行して実行する 2 つのスレッドに移動し、合計処理時間を 6 分から 3 強に短縮しました。
事例:科学・工学シミュレーションソフト。テスト対象 (星核、核爆発、昆虫個体群の地理的分散など) を表す 3 次元グリッド内のすべてのポイントで何らかの効果 (熱流など) を計算することによって解決される問題はたくさんあります。基本的に、すべてのポイントで同じ計算が行われ、多くのポイントで行われるため、それらを並行して実行することは理にかなっています。
これらすべてのケースやその他多くのケースで、2 つのコンピューティング プロセスがほぼ同時に同じメモリ (= 必要に応じて変数) にアクセスすると、それらが互いに干渉し、互いの作業を台無しにする可能性があります。「並行プログラミング」を扱うコンピュータ サイエンスの巨大な部門では、この種の問題を解決する方法についてのアイデアを扱っています。
このトピックのかなり有用な開始議論は、ウィキペディアで見つけることができます。
ロックレス同時実行の利点は、プログラムの複雑さがなくなることです。命令型言語では、並行プログラミングはロックに依存しており、プログラムがある程度複雑になると、修正が困難なデッドロック バグが忍び寄ります。
このような「ロックレス並行性」は、実際には言語の機能ではありません。むしろ、それはプラットフォームまたはランタイム環境の機能であり、これらの機能へのアクセスを提供するために邪魔にならない言語は悲惨です。
ロックベースの同時実行性とロックフリーの同時実行性の間のトレードについて考えることは、メタサーキュラーエバリュエーターの問題に類似しています。アトミック操作(コンペアアンドスワップ、CASなど)の観点からロックを実装でき、アトミック操作の観点から実装できます。ロックの。どちらが一番下にあるべきですか?