我最近試圖寫一個鎖語句的例子。請考慮下面的代碼:爲什麼一開始就有線程競賽?
public partial class Form1 : Form
{
private class Concurrency
{
private int _myValue;
private object _locker = new object();
public int Value
{
set
{
lock (_locker)
{
_myValue = value;
Thread.Sleep(new Random().Next(5, 25));
}
}
get
{
return _myValue;
}
}
}
private Random _random;
private Concurrency _concurrency;
public Form1()
{
InitializeComponent();
_random = new Random();
_concurrency = new Concurrency();
}
private void button1_Click(object sender, EventArgs e)
{
CreateTask(1);
CreateTask(2);
}
private void CreateTask(int taskId)
{
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 10; ++i)
{
int randomNumber = _random.Next(0, 50);
Console.WriteLine("Thread {0}, setting value {1}", taskId, randomNumber);
_concurrency.Value = randomNumber;
Console.WriteLine("Thread {0}, getting value {1}", taskId, _concurrency.Value);
Thread.Sleep(_random.Next(5, 15));
}
});
}
}
結果是:
Thread 2, setting value 4
Thread 1, setting value 22
Thread 2, getting value 22
Thread 1, getting value 22
Thread 2, setting value 11
Thread 2, getting value 11
Thread 1, setting value 8
Thread 2, setting value 41
Thread 1, getting value 8
Thread 1, setting value 30
Thread 2, getting value 41
Thread 1, getting value 30
Thread 2, setting value 18
Thread 1, setting value 42
Thread 2, getting value 18
Thread 2, setting value 30
Thread 1, getting value 42
Thread 1, setting value 24
Thread 2, getting value 30
Thread 1, getting value 24
Thread 2, setting value 13
Thread 1, setting value 7
Thread 2, getting value 13
Thread 2, setting value 13
Thread 1, getting value 7
Thread 2, getting value 13
Thread 1, setting value 38
Thread 2, setting value 19
Thread 1, getting value 38
Thread 1, setting value 4
Thread 2, getting value 19
Thread 2, setting value 44
Thread 1, getting value 4
Thread 2, getting value 44
Thread 1, setting value 48
Thread 2, setting value 12
Thread 1, getting value 48
Thread 1, setting value 47
Thread 2, getting value 12
Thread 1, getting value 47
正如你所看到的,一切都很好,但事先設置/獲取情況:線程2套值2,但得到22而且它不是單一的情況下,它每次都發生。我知道設置和獲取不是原子的,應該圍繞任務中的指令設置鎖定,但爲什麼第一次嘗試總是失敗並且其他工作正常?
編輯:
我更新併發類這樣的:
private class Concurrency
{
private static Random _random = new Random();
private int _myValue;
private object _locker = new object();
public int Value
{
set
{
lock (_locker)
{
_myValue = value;
Thread.Sleep(_random.Next(5, 250));
}
}
get
{
return _myValue;
}
}
}
請注意,我還擴大了時間範圍的Thread.Sleep。結果是:
Thread 2, setting value 3
Thread 1, setting value 9
Thread 2, getting value 9
Thread 2, setting value 44
Thread 1, getting value 9
Thread 1, setting value 35
Thread 2, getting value 44
Thread 2, setting value 32
Thread 1, getting value 35
Thread 1, setting value 25
Thread 2, getting value 32
Thread 2, setting value 15
Thread 1, getting value 25
Thread 1, setting value 5
Thread 2, getting value 15
Thread 2, setting value 34
Thread 1, getting value 5
Thread 1, setting value 42
Thread 2, getting value 34
Thread 2, setting value 36
Thread 1, getting value 42
Thread 1, setting value 8
Thread 2, getting value 36
Thread 2, setting value 42
Thread 1, getting value 8
Thread 1, setting value 16
Thread 2, getting value 42
Thread 2, setting value 0
Thread 1, getting value 16
Thread 1, setting value 43
Thread 2, getting value 0
Thread 2, setting value 20
Thread 1, getting value 43
Thread 1, setting value 30
Thread 2, getting value 20
Thread 2, setting value 38
Thread 1, getting value 30
Thread 1, setting value 0
Thread 2, getting value 38
Thread 1, getting value 0
確實沒有什麼變化。我猜這不是Random問題,而是其他一些問題。
嘗試拉出for循環(從任務內部到button1_Click例程)... – 2013-03-04 13:10:19