我正在練習 C# 中的執行緒和并發性,并嘗試使用一個執行緒進行偶數排序和另一個用于奇數排序的執行緒來實作基本的奇偶排序演算法。
static bool Sort(int startPosition, List<int> list)
{
bool result = true;
do
{
for (int i = startPosition; i <= list.Count - 2; i = i 2)
{
if (list[i] > list[i 1])
{
int temp = list[i];
list[i] = list[i 1];
list[i 1] = temp;
result = false;
}
}
} while (!result);
return result;
}
而主要方法是這樣的:
static void Main(string[] args)
{
bool isOddSorted = false;
bool isEvenSorted = false;
List<int> list = new List<int>();
while (list.Count < 15)
{
list.Add(new Random().Next(0, 20));
}
var evenThread = new Thread(() =>
{
isEvenSorted = Sort(0, list);
});
evenThread.Start();
var oddThread = new Thread(() =>
{
isOddSorted = Sort(1, list);
});
oddThread.Start();
while (true)
{
if (isEvenSorted && isOddSorted)
{
foreach (int i in list)
{
Console.WriteLine(i);
}
break;
}
}
}
可以理解,Sort 方法中的回圈將永遠作業,因為結果變數從未設定為 true。然而,它的作業方式設法對串列進行排序。它只是不會在任何時候破裂。
然而,當我在 Sort 函式的 do-scope 的第一行添加“result = true”時,排序就混亂了。 
我不知道如何解決這個問題。
uj5u.com熱心網友回復:
您不能以多執行緒方式輕松進行奇偶排序。為什么?因為奇偶排序本質上是兩次排序程序(奇數和偶數遍)的重復,任何后續遍都取決于前一遍的結果。實際上,您不能并行/同時運行兩次傳遞,因為每次傳遞都必須相互跟隨。
當然有使用多執行緒的方法,即使是奇偶排序,盡管這可能沒有多大實際意義。例如,您可以將串列分成幾個磁區,每個磁區獨立進行奇偶排序。每個磁區的排序可以以多執行緒方式完成。作為最后一步,它需要以導致完全排序的串列的方式合并已排序的磁區。
(順便說一句,如果你只讓do while你的Sort方法中的回圈運行很多次,你最終會得到一個排序的串列,這只是給了足夠的時間,即使“重疊”并發傳遞你最終會得到一個排序的串列,但也許不是與原始串列中的所有數字相同。因為給定足夠多的回圈重復,最終元素將相互比較并洗牌到正確的位置。但是,由于您沒有同步串列訪問,您可能會丟失一些數字串列,根據運行時行為和兩個執行緒之間串列訪問的時間,替換為其他數字的重復項。)
uj5u.com熱心網友回復:
您正在嘗試跨執行緒修改非執行緒安全集合。
即使假設是好的 - 您正在使用基本的交換Sort方法(但您沒有完全正確地實作它),您必須考慮到當一個執行緒正在進行交換時,另一個執行緒可以交換一個值在作為temp變數在這個確切時刻。
您需要熟悉鎖和/或執行緒安全集合。
uj5u.com熱心網友回復:
查看您的result變數以及您針對result.
外do ... while (!result)回圈只會在result為true時退出。
現在想象您的內部for回圈找到兩個需要交換的數字。所以它會交換數字。并設定result為false。這是我要問你的問題:當兩個數字交換后,Afterresult被設定為false,何時何地result被設定為true?
此外,當您對偶數串列位置的每個數字和奇數位置的每個數字進行排序時,您的代碼不會對整個串列進行最終排序。因此,基本上,如果在進行偶數和奇數排序后,偶數位置上的較大數字n后跟奇數位置上的較小數字n 1,則您的代碼將其保留在該位置,使串列基本上仍然(部分)未排序......
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/361539.html
