2

スレッド A とスレッド B の 2 つのスレッドがあるとします。スレッド A がオブジェクトを値に設定し、それをオブジェクト X と呼び、スレッド B が来て、スレッドによって設定されている間にそのオブジェクトを取得しようとすると、C# で何が起こるかあ?C# は例外をスローしますか? B は、A が変更を加える前にオブジェクト X を受け取りますか? それとも、A が変更を加えた後に B はオブジェクト X を受け取りますか?

明らかだと思いましたが、コードは次のとおりです(同期を追加しても、これが上記の正確なケースを引き起こすかどうかはまだ100%確信が持てません):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication8 {
    public partial class Form1 : Form {
        private AutoResetEvent waitEvent = new AutoResetEvent(false);
        int objectX = 0;

        public Form1() {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e) {
            DateTime startTime = DateTime.Now;
            Console.WriteLine("---------------------------- START @ " + startTime + " ----------------------------------------------------------------------");
            Thread A = new Thread(ThreadAWorkMethod);
            Thread B = new Thread(ThreadBWorkMethod);
            objectX = 0;
            waitEvent = new AutoResetEvent(false);
            A.Start();
            B.Start();
            A.Join();
            B.Join();
            Console.WriteLine("---------------------------- FINISHED AFTER " + (DateTime.Now - startTime).TotalMilliseconds + " ----------------------------");
        }

        public void ThreadAWorkMethod() {
            waitEvent.WaitOne();
            objectX = 5;
            Console.WriteLine("Value has been changed to: " + objectX + " in thread A at " + DateTime.Now);
            return;
        }

        public void ThreadBWorkMethod() {
            waitEvent.Set();
            string xInThreadB = objectX.ToString();
            Console.WriteLine("Value in thread B: " + xInThreadB + " at " + DateTime.Now);
            return;
        }
    }
}

スレッド B のコンソールへの出力は 0 または 5 のように見えますが、どちらのスレッドも同じタイムスタンプを持つため、DateTime をチェックしてもどちらのスレッドが最初に処理されたかを特定することはできません...そして 1 つの出力で常にそれが行われます最初にコンソールに、つまり、誰が最初にサービスを提供したか、およびスレッドが get-set で実際に衝突したかどうかを言います。したがって、一部の人が言及しているように、最終的には、ロックはより低いフレームワーク レベルから C# の変数に実装されているようです。

4

3 に答える 3

3

C# は例外をスローしますか

いいえ、そうではないでしょう。ランタイムには、この条件を自動的にチェックして例外を発生させるものはありません。

ただし、設定されている「値」はその時点で有効な状態である場合とそうでない場合があるため、結果が使用されるとすぐに、値を使用するものは何でも簡単に例外を発生させる可能性があります。

A がオブジェクト X を変更する前に B がオブジェクト X を受け取るか、または A がオブジェクトを変更した後に B がオブジェクト X を受け取るか?

どちらでも可能です。また、「オブジェクト」のタイプによっては、B が無効な状態でオブジェクトを受け取る可能性もあります。

複数のスレッドが値にアクセスすることがわかっている場合は、常にプロパティへのアクセスを同期するように注意する必要があります。lock(比較的) 単純なステートメントの使用から、他のより複雑な同期オプション ( ReaderWriterLock/ ReaderWriterLockSlimMutex、など)まで、同期には多くのオプションがありますSemaphore

于 2012-08-15T18:09:53.083 に答える
1

それで、このようなものは?

public class Test
{
    public Test()
    {
        DateTime now = DateTime.Now;
        Debug.WriteLine("Test started.");
        A.Start();
        B.Start();
        A.Join();
        B.Join();
        Debug.WriteLine("Total time, in milliseconds, that you just spent in order to save StackOverflow members several minutes of their time: " + (DateTime.Now - now).TotalMilliseconds + " :)");
    }

    int objectX = 0;

    Thread A = new Thread(ThreadAWorkMethod);
    Thread B = new Thread(ThreadBWorkMethod);

    public void ThreadAWorkMethod()
    {
        objectX = 5;
        Debug.WriteLine("Value has been changed to: " + objectX.ToString() + "at " DateTime.Now.Milliseconds);
        return;
    }
    public void ThreadBWorkMethod()
    {
        string xInThreadB = objectX.ToString();
        Debug.WriteLine("Value in thread b: " + xInThreadB + "at " DateTime.Now.Milliseconds);
        return;
    }
}

わかりません、試してみてください:)

于 2012-08-15T18:09:19.900 に答える
0

C# Threading: a race condition exampleと同様の質問になる可能性があります。

PS: .NET Frameworkにlockandがあるのはそのためです。mutex

于 2012-08-15T18:09:23.760 に答える