8

CPython の現在の実装には、「GIL」または「Global Interpreter Lock」と呼ばれるオブジェクトがあります。これは基本的に、2 つの Python スレッドが同時に Python コードを実行するのを防ぐミューテックスです。これにより、2 つのスレッドが Python インタープリターの状態を破壊することを防ぎますが、複数のスレッドが実際に一緒に実行されることも防ぎます。基本的に、これを行うと:

# Thread A
some_list.append(3)
# Thread B
some_list.append(4)

リストを壊すことはできません。なぜなら、実行するスレッドは GIL を保持している必要があるためです。ここで、リスト内の項目が不定の順序で追加される可能性がありますが、ポイントは、リストが破損していないことであり、常に 2 つのものが追加されます。

では、C# に移ります。C# は基本的に Python と同じ問題に直面しています。誰かがそれを知っているなら、私はJavaの話を聞くことにも興味があります.


明確化:特に VM に対して、明示的なロック ステートメントなしで何が起こるかに興味があります。Java と C# の両方にロック プリミティブが存在することは承知しています。それらは Python にも存在します。GIL は、インタープリターを正常に保つ以外に、マルチスレッド コードには使用されません。上記の直接の同等物に興味があるので、十分に覚えていれば、C# で... :-)

List<String> s;
// Reference to s is shared by two threads, which both execute this:
s.Add("hello");
// State of s?
// State of the VM? (And if sane, how so?)

別の例を次に示します。

class A
{
    public String s;
}
// Thread A & B
some_A.s = some_other_value;

// some_A's state must change: how does it change?
// Is the VM still in good shape afterwards?

私は悪い C# コードを書くつもりはありませんlock。ステートメントを理解しています。Python でも、GIL は魔法のようなマルチスレッド コードを提供しません。共有リソースをロックする必要があります。しかし、GIL は Python の「VM」が破損するのを防ぎます。私が興味を持っているのはこの動作です。

4

6 に答える 6

11

スレッド化をサポートする他のほとんどの言語には、Python GIL に相当するものはありません。暗黙的または明示的にミューテックスを使用する必要があります。

于 2010-10-26T17:33:54.197 に答える
4

lock を使用すると、次のようになります。

lock(some_list)
{
    some_list.Add(3);
}

そしてスレッド2で:

lock(some_list)
{
    some_list.Add(4);
}

このステートメントは、この場合、ステートメントlock内のオブジェクトに一度に 1 つのスレッドのみがアクセスできるようにします。詳細については、 http://msdn.microsoft.com/en-us/library/c5kehkcz (VS.80).aspx を参照してください。locksome_list

于 2010-10-26T17:32:26.733 に答える
3

C# には、GIL に相当する Python はありません。

どちらも同じ問題に直面していますが、設計目標が異なっています。

GIL を使用すると、CPythonは 2 つのスレッドからのリストの追加などの操作が簡単になります。これは、一度に 1 つのスレッドしか実行できないことも意味します。これ により、リストと辞書がスレッド セーフになります。これにより、作業がよりシンプルで直感的になりますが、マルチコアでマルチスレッドの利点を活用することが難しくなります。

GIL がない場合、C#はその逆になります。整合性の負担がプログラムの開発者にあることを保証しますが、複数のスレッドを同時に実行することを利用できます。

議論の1つによると -

CPython の GIL は、オブジェクトが一貫した状態に保たれるようにするために、オブジェクトごとに大きなロックと同期を行うという純粋な設計上の選択です。これはトレードオフで構成されています - マルチスレッドのフルパワーを放棄します。

ほとんどの問題はこの欠点に悩まされることはなく、必要な場合にのみこの問題を解決するのに役立つライブラリがあります。つまり、特定のクラスの問題については、マルチコアを利用する負担が開発者に渡され、残りはよりシンプルで直感的なアプローチを楽しむことができます。

注: IronPython などの他の実装には GIL がありません。

于 2010-10-26T17:54:02.097 に答える
1

議論しているクラスに相当する Javaのドキュメントを参照すると、有益な場合があります。

この実装は同期されていないことに注意してください。複数のスレッドがインスタンスに同時にアクセスArrayListし、少なくとも 1 つのスレッドがリストを構造的に変更する場合は、外部で同期する必要があります。(構造変更とは、1 つまたは複数の要素を追加または削除する操作、またはバッキング配列のサイズを明示的に変更する操作です。要素の値を設定するだけでは構造変更ではありません。)リスト。そのようなオブジェクトが存在しない場合は、Collections.synchronizedListメソッドを使用してリストを「ラップ」する必要があります。これは、リストへの偶発的な非同期アクセスを防ぐために、作成時に行うのが最適です。

List list = Collections.synchronizedList(new ArrayList(...));

このクラスの iterator および listIterator メソッドによって返される反復子は、フェイルファストです。反復子の作成後にリストが構造的に変更された場合、反復子自体の remove または add メソッド以外の方法で、反復子は をスローしConcurrentModificationExceptionます。したがって、同時変更に直面した場合、反復子は、将来の不確定な時点で恣意的で非決定論的な動作を危険にさらすのではなく、迅速かつ明確に失敗します。

イテレータのフェイルファスト動作は保証できないことに注意してください。一般的に言えば、同期されていない同時変更が存在する場合にハードな保証を行うことは不可能であるためです。フェイルファスト イテレータConcurrentModificationExceptionは、ベスト エフォート ベースでスローします。したがって、その正確性をこの例外に依存するプログラムを作成するのは誤りです。反復子のフェイルファスト動作は、バグを検出するためだけに使用する必要があります

于 2010-10-26T17:53:56.043 に答える
0

複数のスレッドでロックせずに使用すると、ほとんどの複雑なデータ構造 (リストなど) が破損する可能性があります。

参照の変更はアトミックであるため、参照は常に有効な参照のままです。

しかし、セキュリティ クリティカルなコードと対話する場合に問題があります。したがって、重要なコードで使用されるデータ構造は、次のいずれかになります。

  • 信頼されていないコードからはアクセスできず、信頼されているコードによって正しくロック/使用されている
  • 不変 (文字列クラス)
  • 使用前にコピー (valuetype パラメータ)
  • 信頼できるコードで記述され、内部ロックを使用して安全な状態を保証します

たとえば、重要なコードは、信頼されていないコードからアクセスできるリストを信頼できません。List で渡された場合は、プライベート コピーを作成し、そのコピーに対して前提条件チェックを実行してから、そのコピーを操作する必要があります。

于 2010-10-26T18:01:22.857 に答える
0

質問の本当の意味を勝手に推測してみます...

Python では、Python が参照カウントの形式を使用しているため、インタープリターのデータ構造が破損します。

C# と Java はどちらもガベージ コレクションを使用しますが、実際に完全なヒープ コレクションを実行するときにグローバル ロックを使用します。

データは、ロックなしで「世代」間でマークおよび移動できます。しかし、実際にクリーンアップするには、すべてを停止する必要があります。うまくいけば、非常に短い停止ですが、完全な停止です。

2007 年時点のCLRガベージ コレクションに関する興味深いリンクを次に示します。

于 2010-10-26T18:56:27.693 に答える