Donato  Roob

Donato Roob

1628866620

IntelliJ Rust for the 2021.2 Release Cycle

For IntelliJ Rust, this release cycle has been full of significant updates. We have added new functionality to language support, code insight, and run/debug support, along with many fixes and smaller enhancements.

#rust 

What is GEEK

Buddha Community

IntelliJ Rust for the 2021.2 Release Cycle
伊藤  直子

伊藤 直子

1633693200

【 初心者向け】C言語でのマルチスレッド の概要

ニューヨークで働き、ウォール街中のプログラマーと話をしていると、ほとんどのリアルタイムプログラミングアプリケーションで期待される共通の知識の糸に気づきました。その知識はマルチスレッドとして知られています。私はプログラミングの世界を移動し、潜在的なプログラミング候補者にインタビューを行ったので、マルチスレッドについてほとんど知られていないことや、スレッドが適用される理由や方法に驚かされることは決してありません。Vance Morrisonによって書かれた一連の優れた記事で、MSDNはこの問題に対処しようとしました:(MSDNの8月号、すべての開発者がマルチスレッドアプリについて知っておくべきこと、および10月号はマルチスレッドでのローロック技術の影響を理解するを参照してください)。アプリ

この記事では、スレッド化、スレッド化が使用される理由、および.NETでのスレッド化の使用方法について紹介します。マルチスレッドの背後にある謎を完全に明らかにし、それを説明する際に、コード内の潜在的なスレッド障害を回避するのに役立つことを願っています。

スレッドとは何ですか?

すべてのアプリケーションは、少なくとも1つのスレッドで実行されます。では、スレッドとは何ですか?スレッドはプロセスにすぎません。私の推測では、糸という言葉は、織機で糸を織り上げる超自然的なミューズのギリシャ神話に由来していると思います。各糸は、誰かの人生の時間の道を表しています。あなたがその糸をいじると、あなたは人生の構造を乱したり、人生のプロセスを変えたりします。コンピューターでは、スレッドは時間の経過とともに移動するプロセスです。プロセスは一連の順次ステップを実行し、各ステップはコード行を実行します。ステップは連続しているため、各ステップには一定の時間がかかります。一連のステップを完了するのにかかる時間は、各プログラミングステップの実行にかかる時間の合計です。

マルチスレッドアプリケーションとは何ですか?

長い間、ほとんどのプログラミングアプリケーション(組み込みシステムプログラムを除く)はシングルスレッドでした。これは、アプリケーション全体でスレッドが1つしかないことを意味します。計算Bが完了するまで、計算Aを実行することはできません。プログラムはステップ1から始まり、最後のステップ(ステップ10と呼びます)に到達するまで順次続行します(ステップ2、ステップ3、ステップ4)。マルチスレッドアプリケーションを使用すると、複数のスレッドを実行できます。各スレッドは独自のプロセスで実行されます。したがって、理論的には、あるスレッドでステップ1を実行し、同時に別のスレッドでステップ2を実行できます。同時に、ステップ3を独自のスレッドで実行し、ステップ4を独自のスレッドで実行することもできます。したがって、ステップ1、ステップ2、ステップ3、およびステップ4は同時に実行されます。理論的には、4つのステップすべてがほぼ同時にかかった場合、シングルスレッドの実行にかかる時間の4分の1でプログラムを終了できます(4プロセッサマシンを使用していると仮定)。では、なぜすべてのプログラムがマルチスレッド化されていないのでしょうか。スピードとともに、あなたは複雑さに直面するからです。ステップ1がステップ2の情報に何らかの形で依存している場合を想像してみてください。ステップ1がステップ2の前に計算を終了した場合、またはその逆の場合、プログラムが正しく実行されない可能性があります。

珍しいアナロジー

マルチスレッドを考える別の方法は、人体を考慮することです。体の各器官(心臓、肺、肝臓、脳)はすべてプロセスに関与しています。各プロセスは同時に実行されています。各臓器がプロセスのステップとして実行された場合を想像してみてください。最初に心臓、次に脳、次に肝臓、次に肺です。私たちはおそらく死んでしまうでしょう。つまり、人体は1つの大きなマルチスレッドアプリケーションのようなものです。すべての臓器は同時に実行されるプロセスであり、これらのプロセスはすべて相互に依存しています。これらのプロセスはすべて、神経信号、血流、化学的トリガーを介して通信します。すべてのマルチスレッドアプリケーションと同様に、人体は非常に複雑です。一部のプロセスが他のプロセスから情報を取得しない場合、または特定のプロセスが遅くなったり速くなったりすると、医学的な問題が発生します。それか'

いつスレッド化するか

マルチスレッドは、プログラムをより効率的に実行したい状況で最もよく使用されます。たとえば、ウィンドウフォームプログラムの中に、実行に1秒以上かかり、繰り返し実行する必要のあるメソッド(method_Aと呼びます)が含まれているとします。プログラム全体が単一のスレッドで実行された場合、ボタンの押下が正しく機能しなかったり、入力が少し遅くなったりすることがあります。method_Aの計算量が多すぎると、ウィンドウフォームの特定の部分がまったく機能しないことに気付くかもしれません。この許容できないプログラムの動作は、プログラムにマルチスレッドが必要であることを示しています。スレッド化が必要になるもう1つの一般的なシナリオは、メッセージングシステムです。アプリケーションに多数のメッセージが送信されている場合は、メインの処理プログラムの実行と同時にそれらをキャプチャし、適切に配布する必要があります。重い処理を実行しているときに一連のメッセージを効率的にキャプチャすることはできません。そうしないと、メッセージを見逃す可能性があります。複数のスレッドは、複数のプロセスが同時に実行される組立ライン方式で使用することもできます。たとえば、プロセスがスレッドでデータを収集すると、1つのプロセスがデータをフィルタリングし、1つのプロセスがデータをデータベースと照合します。これらの各シナリオはマルチスレッドの一般的な使用法であり、シングルスレッドで実行されている同様のアプリケーションのパフォーマンスを大幅に向上させます。そうしないと、メッセージを見逃す可能性があるためです。複数のスレッドは、複数のプロセスが同時に実行される組立ライン方式で使用することもできます。たとえば、プロセスがスレッドでデータを収集すると、1つのプロセスがデータをフィルタリングし、1つのプロセスがデータをデータベースと照合します。これらの各シナリオはマルチスレッドの一般的な使用法であり、シングルスレッドで実行されている同様のアプリケーションのパフォーマンスを大幅に向上させます。そうしないと、メッセージを見逃す可能性があるためです。複数のスレッドは、複数のプロセスが同時に実行される組立ライン方式で使用することもできます。たとえば、プロセスがスレッドでデータを収集すると、1つのプロセスがデータをフィルタリングし、1つのプロセスがデータをデータベースと照合します。これらの各シナリオはマルチスレッドの一般的な使用法であり、シングルスレッドで実行されている同様のアプリケーションのパフォーマンスを大幅に向上させます。

スレッドしない場合

初心者のプログラマーが最初にスレッド化を学ぶとき、彼らはプログラムでスレッド化を使用する可能性に魅了される可能性があります。彼らは実際にスレッドハッピーになるかもしれません  詳しく説明させてください、

1日目)プログラマーは、スレッドを生成できることを学び、プログラムで1つの新しいスレッドCool!の作成を開始します 。

2日目)プログラマーは、「プログラムの一部で他のスレッドを生成することで、これをさらに効率的にすることができます!」と言います。

3日目)P:「わあ、スレッド内でスレッドをフォークすることもでき、本当に効率が向上します!!」

4日目)P:「奇妙な結果が出ているようですが、それは問題ありません。今は無視します。」

5日目)「うーん、widgetX変数に値がある場合もありますが、まったく設定されていないように見える場合もあります。コンピューターが機能していないため、デバッガーを実行するだけです」。

9日目)「このくそったれ(より強い言語)プログラムはあちこちでジャンプしています!!何が起こっているのか理解できません!」

2週目)時々、プログラムはただそこに座って、まったく何もしません!ヘルプ!!!!!

おなじみですか?マルチスレッドプログラムを初めて設計しようとしたほとんどの人は、スレッドの設計知識が豊富であっても、おそらくこれらの毎日の箇条書きの少なくとも1つまたは2つを経験したことがあります。スレッド化が悪いことだとほのめかしているわけではありません。プログラムでスレッド化の効率を上げるプロセスでは、非常に注意してください。  シングルスレッドプログラムとは異なり、同時に多くのプロセスを処理しているため、複数の従属変数を持つ複数のプロセスを追跡するのは非常に難しい場合があります。ジャグリングと同じようにマルチスレッドを考えてください。手で1つのボールをジャグリングするのは(退屈ではありますが)かなり簡単です。ただし、これらのボールのうち2つを空中に置くように挑戦された場合、その作業は少し難しくなります。3、4、および5の場合、ボールは次第に難しくなります。ボールの数が増えると、実際にボールを落とす可能性が高くなります。 一度にたくさんのボールをジャグリングするには、知識、スキル、正確なタイミングが必要です。マルチスレッドもそうです。 

マルチスレッド

図1-マルチスレッドはジャグリングプロセスのようなものです

 
スレッディングの問題

プログラム内のすべてのプロセスが相互に排他的である場合、つまり、プロセスが他のプロセスにまったく依存していない場合、複数のスレッド化は非常に簡単で、問題はほとんど発生しません。各プロセスは、他のプロセスに煩わされることなく、独自のハッピーコースで実行されます。ただし、複数のプロセスが他のプロセスによって使用されているメモリの読み取りまたは書き込みを行う必要がある場合、問題が発生する可能性があります。たとえば、プロセス#1とプロセス#2の2つのプロセスがあるとします。両方のプロセスが変数Xを共有します。スレッドプロセス#1が最初に値5の変数Xを書き込み、スレッドプロセス#2が次に値-3の変数Xを書き込む場合、Xの最終値は-3です。ただし、プロセス#2が最初に値-3の変数Xを書き込み、次にプロセス#1が値5の変数Xを書き込む場合、Xの最終値は5です。Xを設定できるプロセスがプロセス#1またはプロセス#2の知識を持っていない場合、Xは、最初にXに到達したスレッドに応じて異なる最終値になる可能性があります。シングルスレッドプログラムでは、すべてが順番に続くため、これが発生する可能性はありません。シングルスレッドプログラムでは、並列に実行されているプロセスがないため、Xは常に最初にメソッド#1によって設定され(最初に呼び出された場合)、次にメソッド#2によって設定されます。シングルスレッドプログラムには驚きはありません。それはステップバイステップです。マルチスレッドプログラムを使用すると、2つのスレッドが同時にコードを入力し、結果に大混乱をもたらす可能性があります。スレッドの問題は、同時に実行されている別のスレッドが同じコードを入力して共有データを操作できるようにしながら、共有メモリにアクセスする1つのスレッドを制御する何らかの方法が必要なことです。Xは、どのスレッドが最初にXに到達したかによって、最終的に異なる最終値になる可能性があります。シングルスレッドプログラムでは、すべてが順番に続くため、これが発生する可能性はありません。シングルスレッドプログラムでは、並列に実行されているプロセスがないため、Xは常に最初にメソッド#1によって設定され(最初に呼び出された場合)、次にメソッド#2によって設定されます。シングルスレッドプログラムには驚きはありません。それはステップバイステップです。マルチスレッドプログラムを使用すると、2つのスレッドが同時にコードを入力し、結果に大混乱をもたらす可能性があります。スレッドの問題は、同時に実行されている別のスレッドが同じコードを入力して共有データを操作できるようにしながら、共有メモリにアクセスする1つのスレッドを制御する何らかの方法が必要なことです。Xは、どのスレッドが最初にXに到達したかによって、最終的に異なる最終値になる可能性があります。シングルスレッドプログラムでは、すべてが順番に続くため、これが発生する可能性はありません。シングルスレッドプログラムでは、並列に実行されているプロセスがないため、Xは常に最初にメソッド#1によって設定され(最初に呼び出された場合)、次にメソッド#2によって設定されます。シングルスレッドプログラムには驚きはありません。それはステップバイステップです。マルチスレッドプログラムを使用すると、2つのスレッドが同時にコードを入力し、結果に大混乱をもたらす可能性があります。スレッドの問題は、同時に実行されている別のスレッドが同じコードを入力して共有データを操作できるようにしながら、共有メモリにアクセスする1つのスレッドを制御する何らかの方法が必要なことです。すべてが順番に続くため、これが発生する可能性はありません。シングルスレッドプログラムでは、並列に実行されているプロセスがないため、Xは常に最初にメソッド#1によって設定され(最初に呼び出された場合)、次にメソッド#2によって設定されます。シングルスレッドプログラムには驚きはありません。それはステップバイステップです。マルチスレッドプログラムを使用すると、2つのスレッドが同時にコードを入力し、結果に大混乱をもたらす可能性があります。スレッドの問題は、同時に実行されている別のスレッドが同じコードを入力して共有データを操作できるようにしながら、共有メモリにアクセスする1つのスレッドを制御する何らかの方法が必要なことです。すべてが順番に続くため、これが発生する可能性はありません。シングルスレッドプログラムでは、並列に実行されているプロセスがないため、Xは常に最初にメソッド#1によって設定され(最初に呼び出された場合)、次にメソッド#2によって設定されます。シングルスレッドプログラムには驚きはありません。それはステップバイステップです。マルチスレッドプログラムを使用すると、2つのスレッドが同時にコードを入力し、結果に大混乱をもたらす可能性があります。スレッドの問題は、同時に実行されている別のスレッドが同じコードを入力して共有データを操作できるようにしながら、共有メモリにアクセスする1つのスレッドを制御する何らかの方法が必要なことです。(最初に呼び出された場合)次に、メソッド#2で設定します。シングルスレッドプログラムには驚きはありません。それはステップバイステップです。マルチスレッドプログラムを使用すると、2つのスレッドが同時にコードを入力し、結果に大混乱をもたらす可能性があります。スレッドの問題は、同時に実行されている別のスレッドが同じコードを入力して共有データを操作できるようにしながら、共有メモリにアクセスする1つのスレッドを制御する何らかの方法が必要なことです。(最初に呼び出された場合)次に、メソッド#2で設定します。シングルスレッドプログラムには驚きはありません。それはステップバイステップです。マルチスレッドプログラムを使用すると、2つのスレッドが同時にコードを入力し、結果に大混乱をもたらす可能性があります。スレッドの問題は、同時に実行されている別のスレッドが同じコードを入力して共有データを操作できるようにしながら、共有メモリにアクセスする1つのスレッドを制御する何らかの方法が必要なことです。 

スレッドセーフ

3つのボールをジャグリングするたびに、空中のボールが、自然の異常によって、すでに右手に座っているボールが投げられるまで、右手に到達することが決して許されなかったと想像してみてください。少年、ジャグリングはずっと簡単でしょう!これがスレッドセーフのすべてです。私たちのプログラムでは、もう一方のスレッドがビジネスを終了している間、一方のスレッドをコードブロック内で待機させます。スレッドのブロックまたはスレッドの同期と呼ばれるこのアクティビティにより、プログラム内で実行される同時スレッドのタイミングを制御できます。C#では、メモリの特定の部分(通常はオブジェクトのインスタンス)をロックし、オブジェクトを使用して別のスレッドが完了するまで、スレッドがこのオブジェクトのメモリのコードを入力できないようにします。今ではおそらくコード例を渇望しているので、ここに行きます。

2スレッドのシナリオを見てみましょう。この例では、C#でスレッド1とスレッド2の2つのスレッドを作成します。どちらも、独自のwhileループで実行されます。スレッドは何の役にも立ちません。どのスレッドに属しているかを示すメッセージを出力するだけです。_threadOutputと呼ばれる共有メモリクラスメンバーを利用します。_threadOutputには、実行中のスレッドに基づいてメッセージが割り当てられます。リスト#1は、それぞれDisplayThread1とDisplayThread2に含まれる2つのスレッドを示しています。

リスト1-メモリ内で共通の変数を共有する2つのスレッドを作成する

// shared memory variable between the two threads  
// used to indicate which thread we are in  
private string _threadOutput = "";  
  
/// <summary>  
/// Thread 1: Loop continuously,  
/// Thread 1: Displays that we are in thread 1  
/// </summary>  
void DisplayThread1()  
{  
      while (_stopThreads == false)  
      {  
            Console.WriteLine("Display Thread 1");  
  
            // Assign the shared memory to a message about thread #1  
            _threadOutput = "Hello Thread1";  
  
  
            Thread.Sleep(1000);  // simulate a lot of processing   
  
            // tell the user what thread we are in thread #1, and display shared memory  
            Console.WriteLine("Thread 1 Output --> {0}", _threadOutput);  
  
      }  
}  

/// <summary>  
/// Thread 2: Loop continuously,  
/// Thread 2: Displays that we are in thread 2  
/// </summary>  
void DisplayThread2()  
{  
      while (_stopThreads == false)  
      {  
        Console.WriteLine("Display Thread 2");  
  
  
       // Assign the shared memory to a message about thread #2  
        _threadOutput = "Hello Thread2";  
  
  
        Thread.Sleep(1000);  // simulate a lot of processing  
  
       // tell the user we are in thread #2  
        Console.WriteLine("Thread 2 Output --> {0}", _threadOutput);  
  
      }  
}
Class1()  
{  
      // construct two threads for our demonstration;  
      Thread thread1 = new Thread(new ThreadStart(DisplayThread1));  
      Thread thread2 = new Thread(new ThreadStart(DisplayThread2));  
  
      // start them  
      thread1.Start();  
      thread2.Start();  
}

このコードの結果を図2に示します。結果を注意深く見てください。プログラムが驚くべき出力を提供することに気付くでしょう(これをシングルスレッドの考え方から見た場合)。_threadOutputを、それが属するスレッドに対応する番号の文字列に明確に割り当てましたが、コンソールでは次のように表示されます。

C#でのスレッド化

図2-2スレッドの例からの異常な出力。

私たちのコードから次のことが期待されます、

スレッド1の出力->ハロースレッド1とスレッド2の出力->ハロースレッド2ですが、ほとんどの場合、結果は完全に予測できません。 

スレッド2の出力->ハロースレッド1とスレッド1の出力->ハロースレッド2が表示されることがあります。スレッドの出力がコードと一致しません。コードを見て、それを目で追っていますが、_threadOutput = "Hello Thread 2"、Sleep、Write "Thread 2-> Hello Thread 2"ですが、このシーケンスで必ずしも最終結果が得られるとは限りません。 

説明

このようなマルチスレッドプログラムでは、理論的にはコードが2つのメソッドDisplayThread1とDisplayThread2を同時に実行しているためです。各メソッドは変数_threadOutputを共有します。したがって、_threadOutputにはスレッド#1で値 "Hello Thread1"が割り当てられ、2行後にコンソールに_threadOutputが表示されますが、スレッド#1がそれを割り当てて表示する時間の間のどこかで、スレッド#2が_threadOutputを割り当てる可能性があります。値「HelloThread2」。これらの奇妙な結果が発生する可能性があるだけでなく、図2に示す出力に見られるように、非常に頻繁に発生します。この痛みを伴うスレッドの問題は、競合状態として知られるスレッドプログラミングで非常に一般的なバグです。 この例は、よく知られているスレッドの問題の非常に単純な例です。この問題は、参照されている変数やスレッドセーフでない変数を指すコレクションなどを介して、プログラマーからはるかに間接的に隠されている可能性があります。図2では症状は露骨ですが、競合状態は非常にまれにしか現れず、1分に1回、1時間に1回、または3日後に断続的に現れる可能性があります。レースは、その頻度が低く、再現が非常に難しいため、おそらくプログラマーにとって最悪の悪夢です。

レースに勝つ

競合状態を回避する最善の方法は、スレッドセーフなコードを作成することです。コードがスレッドセーフである場合、いくつかの厄介なスレッドの問題が発生するのを防ぐことができます。スレッドセーフなコードを書くためのいくつかの防御策があります。1つは、メモリの共有をできるだけ少なくすることです。クラスのインスタンスを作成し、それが1つのスレッドで実行され、次に同じクラスの別のインスタンスを作成し、それが別のスレッドで実行される場合、静的変数が含まれていない限り、クラスはスレッドセーフです。 。2つのクラスはそれぞれ、独自のフィールド用に独自のメモリを作成するため、共有メモリはありません。クラスに静的変数がある場合、またはクラスのインスタンスが他の複数のスレッドによって共有されている場合は、他のクラスがその変数の使用を完了するまで、一方のスレッドがその変数のメモリを使用できないようにする方法を見つける必要があります。ロック。  C#を使用すると、Monitorクラスまたはlock {}構造のいずれかを使用してコードをロックできます。(lock構造は、実際にはtry-finallyブロックを介してMonitorクラスを内部的に実装しますが、プログラマーからこれらの詳細を隠します)。リスト1の例では、共有_threadOutput変数を設定した時点から、コンソールへの実際の出力まで、コードのセクションをロックできます。コードのクリティカルセクションを両方のスレッドでロックして、どちらか一方に競合が発生しないようにします。メソッド内をロックする最も速くて汚い方法は、このポインターをロックすることです。このポインタをロックすると、クラスインスタンス全体がロックされるため、ロック内でクラスのフィールドを変更しようとするスレッドはすべてブロックされます。。ブロッキングとは、変数を変更しようとしているスレッドが、ロックされたスレッドでロックが解除されるまで待機することを意味します。スレッドは、lock {}構造の最後のブラケットに到達すると、ロックから解放されます。

リスト2-2つのスレッドをロックして同期する

/// <summary>  
/// Thread 1, Displays that we are in thread 1 (locked)  
 /// </summary>  
 void DisplayThread1()  
 {  
       while (_stopThreads == false)  
       {  
          // lock on the current instance of the class for thread #1  
             lock (this)  
             {  
                   Console.WriteLine("Display Thread 1");  
                   _threadOutput = "Hello Thread1";  
                   Thread.Sleep(1000);  // simulate a lot of processing  
                   // tell the user what thread we are in thread #1  
                   Console.WriteLine("Thread 1 Output --> {0}", _threadOutput);  
             }// lock released  for thread #1 here  
       }   
 }  

/// <summary>  
/// Thread 1, Displays that we are in thread 1 (locked)  
 /// </summary>  
 void DisplayThread2()  
 {  
       while (_stopThreads == false)  
       {  
  
           // lock on the current instance of the class for thread #2  
             lock (this)  
             {  
                   Console.WriteLine("Display Thread 2");  
                   _threadOutput = "Hello Thread2";  
                   Thread.Sleep(1000);  // simulate a lot of processing  
                   // tell the user what thread we are in thread #1  
                   Console.WriteLine("Thread 2 Output --> {0}", _threadOutput);  
             } // lock released  for thread #2 here  
       }   
 }

2つのスレッドをロックした結果を図3に示します。すべてのスレッド出力が適切に同期されていることに注意してください。スレッド1の出力->ハロースレッド1とスレッド2の出力->ハロースレッド2という結果が常に表示されます。ただし、スレッドのロックにはコストがかかることに注意してください。スレッドをロックすると、ロックが解除されるまで他のスレッドを強制的に待機させます。本質的に、他のスレッドが共有メモリの使用を待機している間、最初のスレッドはプログラムで何もしていないため、プログラムの速度が低下しました。したがって、ロックは慎重に使用する必要があります。共有メモリに関与していない場合は、コード内にあるすべてのメソッドをロックするだけではいけません。また、ロックを使用するときは注意してください。スレッド#1がスレッド#2によってロックが解放されるのを待っている状況に陥りたくないからです。スレッド#2は、スレッド#1によってロックが解放されるのを待っています。この状況が発生すると、両方のスレッドがブロックされ、プログラムがフリーズしたように見えます。この状況はとして知られていますデッドロックが発生し、プログラム内の予測できない断続的な期間にも発生する可能性があるため、競合状態とほぼ同じくらい悪い状況です。 

  C#でのスレッド化

  図3-ロックを使用したデュアルスレッドプログラムの同期

代替ソリューション

.NETは、スレッドの制御に役立つ多くのメカニズムを提供します。別のスレッドが共有メモリの一部を処理している間、スレッドをブロックしたままにする別の方法は、AutoResetEventを使用することです。AutoResetEventクラスには、SetとWaitOneの2つのメソッドがあります。これらの2つの方法は、スレッドのブロックを制御するために一緒に使用できます。AutoResetEventがfalseで初期化されると、プログラムは、AutoResetEventでSetメソッドが呼び出されるまで、WaitOneを呼び出すコード行で停止します。AutoResetEventでSetメソッドが実行されると、スレッドのブロックが解除され、WaitOneを超えて続行できるようになります。次回WaitOneが呼び出されると、自動的にリセットされるため、プログラムは、WaitOneメソッドが実行されているコード行で再び待機(ブロック)します。この「停止とトリガー」を使用できます Setを呼び出して、別のスレッドがブロックされたスレッドを解放する準備ができるまで、あるスレッドをブロックするメカニズム。リスト3は、AutoResetEventを使用して、ブロックされたスレッドが待機し、ブロックされていないスレッドが実行されてコンソールに_threadOutputを表示している間に、互いにブロックする同じ2つのスレッドを示しています。最初に、_blockThread1はfalseを通知するように初期化され、_blockThread2はtrueを通知するように初期化されます。これは、_blockThread2がDisplayThread_2のループを最初に通過するときに、WaitOne呼び出しを続行できるようになる一方で、_blockThread1はDisplayThread_1のWaitOne呼び出しをブロックすることを意味します。_blockThread2がスレッド2のループの終わりに達すると、スレッド1をブロックから解放するためにSetを呼び出して_blockThread1に信号を送ります。次に、スレッド2は、スレッド1がループの終わりに到達して_blockThread2でSetを呼び出すまで、WaitOne呼び出しで待機します。スレッド1で呼び出されたセットはスレッド2のブロックを解放し、プロセスが再開されます。両方のAutoResetEvents(_blockThread1と_blockThread2)を最初にfalseを通知するように設定した場合、両方のスレッドが互いにトリガーする機会なしにループの進行を待機し、デッドロック。 

リスト3-あるいは、AutoResetEventでスレッドをブロックする

AutoResetEvent _blockThread1 = new AutoResetEvent(false);  
AutoResetEvent _blockThread2 = new AutoResetEvent(true);  
  
/// <summary>  
/// Thread 1, Displays that we are in thread 1  
/// </summary>  
void DisplayThread_1()  
{  
      while (_stopThreads == false)  
      {  
               // block thread 1  while the thread 2 is executing  
                _blockThread1.WaitOne();   
  
                // Set was called to free the block on thread 1, continue executing the code  
                  Console.WriteLine("Display Thread 1");  
  
                  _threadOutput = "Hello Thread 1";  
                  Thread.Sleep(1000);  // simulate a lot of processing  
  
                   // tell the user what thread we are in thread #1  
                  Console.WriteLine("Thread 1 Output --> {0}", _threadOutput);  
  
                // finished executing the code in thread 1, so unblock thread 2  
                  _blockThread2.Set();  
      }  
}  
  
/// <summary>  
/// Thread 2, Displays that we are in thread 2  
/// </summary>  
void DisplayThread_2()  
{  
      while (_stopThreads == false)  
      {  
            // block thread 2  while thread 1 is executing  
                  _blockThread2.WaitOne();   
  
            // Set was called to free the block on thread 2, continue executing the code  
                  Console.WriteLine("Display Thread 2");  
  
                  _threadOutput = "Hello Thread 2";  
                  Thread.Sleep(1000);  // simulate a lot of processing  
  
                   // tell the user we are in thread #2  
                  Console.WriteLine("Thread 2 Output --> {0}", _threadOutput);   
  
            // finished executing the code in thread 2, so unblock thread 1  
                _blockThread1.Set();  
      }  
} 

 

リスト3で生成される出力は、図3に示すロックコードと同じ出力ですが、AutoResetEventを使用すると、現在のスレッドが処理を完了したときに、あるスレッドが別のスレッドに通知する方法をより動的に制御できます。

結論

マイクロプロセッサの速度の理論的限界を押し上げているため、テクノロジは、コンピュータテクノロジの速度とパフォーマンスを最適化できる新しい方法を見つける必要があります。マルチプロセッサチップの発明と並列プログラミングへの侵入により、マルチスレッドを理解することで、ムーアの法則に挑戦し続けるために必要な利点をもたらすこれらのより最近のテクノロジーを処理するために必要なパラダイムに備えることができます。C#と.NETは、マルチスレッドと並列処理をサポートする機能を提供します。これらのツールを上手に活用する方法を理解すれば、私たち自身の日々のプログラミング活動において、将来のこれらのハードウェアの約束に備えることができます。一方、シャープなあなたができるので、スレッドのあなたの知識エン.NET可能性を。 

リンク:https://www.c-sharpcorner.com/article/introduction-to-multithreading-in-C-Sharp/

#csharp 

Let Developers Just Need to Grasp only One Button Component

 From then on, developers only need to master one Button component, which is enough.

Support corners, borders, icons, special effects, loading mode, high-quality Neumorphism style.

Author:Newton(coorchice.cb@alibaba-inc.com)

✨ Features

Rich corner effect

Exquisite border decoration

Gradient effect

Flexible icon support

Intimate Loading mode

Cool interaction Special effects

More sense of space Shadow

High-quality Neumorphism style

🛠 Guide

⚙️ Parameters

🔩 Basic parameters

ParamTypeNecessaryDefaultdesc
onPressedVoidCallbacktruenullClick callback. If null, FButton will enter an unavailable state
onPressedDownVoidCallbackfalsenullCallback when pressed
onPressedUpVoidCallbackfalsenullCallback when lifted
onPressedCancelVoidCallbackfalsenullCallback when cancel is pressed
heightdoublefalsenullheight
widthdoublefalsenullwidth
styleTextStylefalsenulltext style
disableStyleTextStylefalsenullUnavailable text style
alignmentAlignmentfalsenullalignment
textStringfalsenullbutton text
colorColorfalsenullButton color
disabledColorColorfalsenullColor when FButton is unavailable
paddingEdgeInsetsGeometryfalsenullFButton internal spacing
cornerFCornerfalsenullConfigure corners of Widget
cornerStyleFCornerStylefalseFCornerStyle.roundConfigure the corner style of Widget. round-rounded corners, bevel-beveled
strokeColorColorfalseColors.blackBorder color
strokeWidthdoublefalse0Border width. The border will appear when strokeWidth > 0
gradientGradientfalsenullConfigure gradient colors. Will override the color
activeMaskColorColorColors.transparentThe color of the mask when pressed
surfaceStyleFSurfacefalseFSurface.FlatSurface style. Default [FSurface.Flat]. See [FSurface] for details

💫 Effect parameters

ParamTypeNecessaryDefaultdesc
clickEffectboolfalsefalseWhether to enable click effects
hoverColorColorfalsenullFButton color when hovering
onHoverValueChangedfalsenullCallback when the mouse enters/exits the component range
highlightColorColorfalsenullThe color of the FButton when touched. effect:true required

🔳 Shadow parameters

ParamTypeNecessaryDefaultdesc
shadowColorColorfalseColors.greyShadow color
shadowOffsetOffsetfalseOffset.zeroShadow offset
shadowBlurdoublefalse1.0Shadow blur degree, the larger the value, the larger the shadow range

🖼 Icon & Loading parameters

ParamTypeNecessaryDefaultdesc
imageWidgetfalsenullAn icon can be configured for FButton
imageMargindoublefalse6.0Spacing between icon and text
imageAlignmentImageAlignmentfalseImageAlignment.leftRelative position of icon and text
loadingboolfalsefalseWhether to enter the Loading state
loadingWidgetWidgetfalsenullLoading widget in loading state. Will override the default Loading effect
clickLoadingboolfalsefalseWhether to enter Loading state after clicking FButton
loadingColorColorfalsenullLoading colors
loadingStrokeWidthdoublefalse4.0Loading width
hideTextOnLoadingboolfalsefalseWhether to hide text in the loading state
loadingTextStringfalsenullLoading text
loadingSizedoublefalse12Loading size

🍭 Neumorphism Style

ParamTypeNecessaryDefaultdesc
isSupportNeumorphismboolfalsefalseWhether to support the Neumorphism style. Open this item [highlightColor] will be invalid
lightOrientationFLightOrientationfalseFLightOrientation.LeftTopValid when [isSupportNeumorphism] is true. The direction of the light source is divided into four directions: upper left, lower left, upper right, and lower right. Used to control the illumination direction of the light source, which will affect the highlight direction and shadow direction
highlightShadowColorColorfalsenullAfter the Neumorphism style is turned on, the bright shadow color

📺 Demo

🔩 Basic Demo

// FButton #1
FButton(
  height: 40,
  alignment: Alignment.center,
  text: "FButton #1",
  style: TextStyle(color: Colors.white),
  color: Color(0xffffab91),
  onPressed: () {},
)

// FButton #2
FButton(
  padding: const EdgeInsets.fromLTRB(12, 8, 12, 8),
  text: "FButton #2",
  style: TextStyle(color: Colors.white),
  color: Color(0xffffab91),
  corner: FCorner.all(6.0),
)

// FButton #3
FButton(
  padding: const EdgeInsets.fromLTRB(12, 8, 12, 8),
  text: "FButton #3",
  style: TextStyle(color: Colors.white),
  disableStyle: TextStyle(color: Colors.black38),
  color: Color(0xffF8AD36),

  /// set disable Color
  disabledColor: Colors.grey[300],
  corner: FCorner.all(6.0),
)

By simply configuring text andonPressed, you can construct an available FButton.

If onPressed is not set, FButton will be automatically recognized as not unavailable. At this time, ** FButton ** will have a default unavailable status style.

You can also freely configure the style of FButton when it is not available via the disabledXXX attribute.

🎈 Corner & Stroke

// #1
FButton(
  width: 130,
  text: "FButton #1",
  style: TextStyle(color: Colors.white),
  color: Color(0xffFF7043),
  onPressed: () {},
  clickEffect: true,
  
  /// 配置边角大小
  ///
  /// set corner size
  corner: FCorner.all(25),
),

// #2
FButton(
  width: 130,
  text: "FButton #2",
  style: TextStyle(color: Colors.white),
  color: Color(0xffFFA726),
  onPressed: () {},
  clickEffect: true,
  corner: FCorner(
    leftBottomCorner: 40,
    leftTopCorner: 6,
    rightTopCorner: 40,
    rightBottomCorner: 6,
  ),
),

// #3
FButton(
  width: 130,
  text: "FButton #3",
  style: TextStyle(color: Colors.white),
  color: Color(0xffFFc900),
  onPressed: () {},
  clickEffect: true,
  corner: FCorner(leftTopCorner: 10),
  
  /// 设置边角风格
  ///
  /// set corner style
  cornerStyle: FCornerStyle.bevel,
  strokeWidth: 0.5,
  strokeColor: Color(0xffF9A825),
),

// #4
FButton(
  width: 130,
  padding: EdgeInsets.fromLTRB(6, 16, 30, 16),
  text: "FButton #4",
  style: TextStyle(color: Colors.white),
  color: Color(0xff00B0FF),
  onPressed: () {},
  clickEffect: true,
  corner: FCorner(
      rightTopCorner: 25,
      rightBottomCorner: 25),
  cornerStyle: FCornerStyle.bevel,
  strokeWidth: 0.5,
  strokeColor: Color(0xff000000),
),

You can add rounded corners to FButton via the corner property. You can even control each fillet individually。

By default, the corners of FButton are rounded. By setting cornerStyle: FCornerStyle.bevel, you can get a bevel effect.

FButton supports control borders, provided that strokeWidth> 0 can get the effect 🥳.

🌈 Gradient


FButton(
  width: 100,
  height: 60,
  text: "#1",
  style: TextStyle(color: Colors.white),
  color: Color(0xffFFc900),
  
  /// 配置渐变色
  ///
  /// set gradient
  gradient: LinearGradient(colors: [
    Color(0xff00B0FF),
    Color(0xffFFc900),
  ]),
  onPressed: () {},
  clickEffect: true,
  corner: FCorner.all(8),
)

Through the gradient attribute, you can build FButton with gradient colors. You can freely build many types of gradient colors.

🍭 Icon

FButton(
  width: 88,
  height: 38,
  padding: EdgeInsets.all(0),
  text: "Back",
  style: TextStyle(color: Colors.white),
  color: Color(0xffffc900),
  onPressed: () {
    toast(context, "Back!");
  },
  clickEffect: true,
  corner: FCorner(
    leftTopCorner: 25,
    leftBottomCorner: 25,),
  
  /// 配置图标
  /// 
  /// set icon
  image: Icon(
    Icons.arrow_back_ios,
    color: Colors.white,
    size: 12,
  ),

  /// 配置图标与文字的间距
  ///
  /// Configure the spacing between icon and text
  imageMargin: 8,
),

FButton(
  onPressed: () {},
  image: Icon(
    Icons.print,
    color: Colors.grey,
  ),
  imageMargin: 8,

  /// 配置图标与文字相对位置
  ///
  /// Configure the relative position of icons and text
  imageAlignment: ImageAlignment.top,
  text: "Print",
  style: TextStyle(color: textColor),
  color: Colors.transparent,
),

The image property can set an image for FButton and you can adjust the position of the image relative to the text, throughimageAlignment.

If the button does not need a background, just set color: Colors.transparent.

🔥 Effect


FButton(
  width: 200,
  text: "Try Me!",
  style: TextStyle(color: textColor),
  color: Color(0xffffc900),
  onPressed: () {},
  clickEffect: true,
  corner: FCorner.all(9),
  
  /// 配置按下时颜色
  ///
  /// set pressed color
  highlightColor: Color(0xffE65100).withOpacity(0.20),
  
  /// 配置 hover 状态时颜色
  ///
  /// set hover color
  hoverColor: Colors.redAccent.withOpacity(0.16),
),

The highlight color of FButton can be configured through the highlightColor property。

hoverColor can configure the color when the mouse moves to the range of FButton, which will be used during Web development.

🔆 Loading

FButton(
  text: "Click top loading",
  style: TextStyle(color: textColor),
  color: Color(0xffffc900),
  ...

  /// 配置 loading 大小
  /// 
  /// set loading size
  loadingSize: 15,

  /// 配置 loading 与文本的间距
  ///
  // Configure the spacing between loading and text
  imageMargin: 6,
  
  /// 配置 loading 的宽
  ///
  /// set loading width
  loadingStrokeWidth: 2,

  /// 是否支持点击自动开始 loading
  /// 
  /// Whether to support automatic loading by clicking
  clickLoading: true,

  /// 配置 loading 的颜色
  ///
  /// set loading color
  loadingColor: Colors.white,

  /// 配置 loading 状态时的文本
  /// 
  /// set loading text
  loadingText: "Loading...",

  /// 配置 loading 与文本的相对位置
  ///
  /// Configure the relative position of loading and text
  imageAlignment: ImageAlignment.top,
),

// #2
FButton(
  width: 170,
  height: 70,
  text: "Click to loading",
  style: TextStyle(color: textColor),
  color: Color(0xffffc900),
  onPressed: () { },
  ...
  imageMargin: 8,
  loadingSize: 15,
  loadingStrokeWidth: 2,
  clickLoading: true,
  loadingColor: Colors.white,
  loadingText: "Loading...",

  /// loading 时隐藏文本
  ///
  /// Hide text when loading
  hideTextOnLoading: true,
)


FButton(
  width: 170,
  height: 70,
  alignment: Alignment.center,
  text: "Click to loading",
  style: TextStyle(color: Colors.white),
  color: Color(0xff90caf9),
  ...
  imageMargin: 8,
  clickLoading: true,
  hideTextOnLoading: true,

  /// 配置自定义 loading 样式
  ///
  /// Configure custom loading style
  loadingWidget: CupertinoActivityIndicator(),
),

Through the loading attribute, you can configure Loading effects for ** FButton **.

When FButton is in Loading state, FButton will enter an unavailable state, onPress will no longer be triggered, and unavailable styles will also be applied.

At the same time loadingText will overwritetext if it is not null.

The click start Loading effect can be achieved through the clickLoading attribute.

The position of loading will be affected by theimageAlignment attribute.

When hideTextOnLoading: true, if FButton is inloading state, its text will be hidden.

Through loadingWidget, developers can set completely customized loading styles.

Shadow


FButton(
  width: 200,
  text: "Shadow",
  textColor: Colors.white,
  color: Color(0xffffc900),
  onPressed: () {},
  clickEffect: true,
  corner: FCorner.all(28),
  
  /// 配置阴影颜色
  ///
  /// set shadow color
  shadowColor: Colors.black87,

  /// 设置组件高斯与阴影形状卷积的标准偏差。
  /// 
  /// Sets the standard deviation of the component's Gaussian convolution with the shadow shape.
  shadowBlur: _shadowBlur,
),

FButton allows you to configure the color, size, and position of the shadow.

🍭 Neumorphism Style

FButton(

  /// 开启 Neumorphism 支持
  ///
  /// Turn on Neumorphism support
  isSupportNeumorphism: true,

  /// 配置光源方向
  ///
  /// Configure light source direction
  lightOrientation: lightOrientation,

  /// 配置亮部阴影
  ///
  /// Configure highlight shadow
  highlightShadowColor: Colors.white,

  /// 配置暗部阴影
  ///
  /// Configure dark shadows
  shadowColor: mainShadowColor,
  strokeColor: mainBackgroundColor,
  strokeWidth: 3.0,
  width: 190,
  height: 60,
  text: "FWidget",
  style: TextStyle(
      color: mainTextTitleColor, fontSize: neumorphismSize_2_2),
  alignment: Alignment.center,
  color: mainBackgroundColor,
  ...
)

FButton brings an incredible, ultra-high texture Neumorphism style to developers.

Developers only need to configure the isSupportNeumorphism parameter to enable and disable the Neumorphism style.

If you want to adjust the style of Neumorphism, you can make subtle adjustments through several attributes related to Shadow, among which:

shadowColor: configure the shadow of the shadow

highlightShadowColor: configure highlight shadow

FButton also provides lightOrientation parameters, and even allows developers to adjust the care angle, and has obtained different Neumorphism effects.

😃 How to use?

Add dependencies in the project pubspec.yaml file:

🌐 pub dependency

dependencies:
  fbutton: ^<version number>

⚠️ Attention,please go to [pub] (https://pub.dev/packages/fbutton) to get the latest version number of FButton

🖥 git dependencies

dependencies:
  fbutton:
    git:
      url: 'git@github.com:Fliggy-Mobile/fbutton.git'
      ref: '<Branch number or tag number>'

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add fbutton_nullsafety

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  fbutton_nullsafety: ^5.0.0

Alternatively, your editor might support or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:fbutton_nullsafety/fbutton_nullsafety.dart';

Download Details:

Author: Fliggy-Mobile

Source Code: https://github.com/Fliggy-Mobile/fbutton

#button  #flutter 

Ahebwe  Oscar

Ahebwe Oscar

1624194540

Django security releases issued: 3.2.4, 3.1.12, and 2.2.24 | Weblog | Django

Django security releases issued: 3.2.4, 3.1.12, and 2.2.24

Posted by Carlton Gibson  on Tháng 6 2, 2021

In accordance with our security release policy, the Django team is issuing Django 3.2.4Django 3.1.12, and Django 2.2.24. These release addresses the security issue detailed below. We encourage all users of Django to upgrade as soon as possible.

CVE-2021-33203: Potential directory traversal via admindocs

Staff members could use the admindocs TemplateDetailView view to check the existence of arbitrary files. Additionally, if (and only if) the default admindocs templates have been customized by the developers to also expose the file contents, then not only the existence but also the file contents would have been exposed.

As a mitigation, path sanitation is now applied and only files within the template root directories can be loaded.

This issue has low severity, according to the Django security policy.

Thanks to Rasmus Lerchedahl Petersen and Rasmus Wriedt Larsen from the CodeQL Python team for the report.

CVE-2021-33571: Possible indeterminate SSRF, RFI, and LFI attacks since validators accepted leading zeros in IPv4 addresses

URLValidatorvalidate_ipv4_address(), and validate_ipv46_address() didn’t prohibit leading zeros in octal literals. If you used such values you could suffer from indeterminate SSRF, RFI, and LFI attacks.

validate_ipv4_address() and validate_ipv46_address() validators were not affected on Python 3.9.5+.

This issue has medium severity, according to the Django security policy.

Affected supported versions

  • Django main branch
  • Django 3.2
  • Django 3.1
  • Django 2.2

#django #weblog #django security releases issued: 3.2.4, 3.1.12, and 2.2.24 #3.2.4 #3.1.12 #2.2.24

Ahebwe  Oscar

Ahebwe Oscar

1624206000

Django bugfix releases issued: 3.2.3, 3.1.11, and 2.2.23 | Weblog | Django

Today we’ve issued 3.2.33.1.11, and 2.2.23 bugfix releases.

The release package and checksums are available from our downloads page, as well as from the Python Package Index. The PGP key ID used for this release is Mariusz Felisiak: 2EF56372BA48CD1B.

#django #weblog #django bugfix releases issued #3.2.3, 3.1.11, and 2.2.23 #django bugfix releases issued: 3.2.3, 3.1.11, and 2.2.23 | weblog | django

Donato  Roob

Donato Roob

1628866620

IntelliJ Rust for the 2021.2 Release Cycle

For IntelliJ Rust, this release cycle has been full of significant updates. We have added new functionality to language support, code insight, and run/debug support, along with many fixes and smaller enhancements.

#rust