多线程中的Bitonic排序(线程冲突)?

时间:2018-01-25 16:58:35

标签: c# multithreading sorting

使用多线程进行正确排序时遇到问题。 Bitonic排序在SingleThread中正常工作,但在MultiThread中返回的结果并不完全正确。有什么问题?我怀疑这可能是一些线程冲突(竞争条件)?

public class MultiThreadedSorter : BaseBitonicSorter
{
    private int minimumLength = 1;

    public override void Sort(ref int[] array)
    {
        a = array;
        minimumLength = a.Length / Environment.ProcessorCount; // przydział procesów
        BitonicSort(new BitonicParameters(0, a.Length, Ascending));
    }

    private void BitonicSort(object AsyncState)
    {
        BitonicParameters parameters = (BitonicParameters)AsyncState;
        if (parameters.Length > 1)
        {
            if (parameters.Length > minimumLength)
            {
                int median = parameters.Length / 2;
                Thread left = new Thread(BitonicSort);
                Thread right = new Thread(BitonicSort);
                left.Start(new BitonicParameters(parameters.Index, median, Ascending));
                right.Start(new BitonicParameters(parameters.Index + median, median, Descending));
                left.Join();
                right.Join();
            }
            else
            {
                int median = (parameters.Length / 2);
                if (median > 1)
                {
                    BitonicSort(new BitonicParameters(parameters.Index, median, Ascending));
                    BitonicSort(new BitonicParameters(parameters.Index, median, Ascending));
                }
            }
            BitonicMerge(new BitonicParameters(parameters.Index, parameters.Length, parameters.Direction));
        }
    }

    private void BitonicMerge(object AsyncState)
    {
        BitonicParameters parameters = (BitonicParameters)AsyncState;
        if (parameters.Length > 1)
        {
            if (parameters.Length > minimumLength)
            {
                int median = (parameters.Length / 2);

                for (int i = parameters.Index; i < (parameters.Index + median); i++)
                {
                    Compare(i, (i + median), parameters.Direction);
                }
                Thread left = new Thread(BitonicMerge);
                Thread right = new Thread(BitonicMerge);
                left.Start(new BitonicParameters(parameters.Index, median, parameters.Direction));
                right.Start(new BitonicParameters(parameters.Index + median, median, parameters.Direction));
                left.Join();
                right.Join();
            }
            else
            {
                int median = (parameters.Length / 2);

                for (int i = parameters.Index; i < (parameters.Index + median); i++)
                {
                    Compare(i, (i + median), parameters.Direction);
                }
                if (median > 1)
                {
                    BitonicMerge(new BitonicParameters(parameters.Index, median, parameters.Direction));
                    BitonicMerge(new BitonicParameters(parameters.Index + median, median, parameters.Direction));
                }
            }
        }
    }

    private struct BitonicParameters
    {
        public BitonicParameters(int index, int length, bool direction)
        {
            Index = index;
            Length = length;
            Direction = direction;
        }
        public int Index;
        public int Length;
        public bool Direction;
    }
}

public class SingleThreadedBitonicSorter : BaseBitonicSorter
{

    public override void Sort(ref int[] array)
    {
        a = array;
        BitonicSort(0, a.Length, Ascending);
    }

    private void BitonicSort(int index, int length, bool direction)
    {
        if (length > 1)
        {
            int median = (length / 2);
            if (median > 1)
            {
                BitonicSort(index, median, Ascending);
                BitonicSort(index + median, median, Descending);
            }
            BitonicMerge(index, length, direction);
        }
    }

    private void BitonicMerge(int index, int length, bool direction)
    {
        if (length > 1)
        {
            int median = (length / 2);

            for (int i = index; i < (index + median); i++)
            {
                Compare(i, (i + median), direction);
            }
            if (median > 1)
            {
                BitonicMerge(index, median, direction);
                BitonicMerge((index + median), median, direction);
            }
        }
    }
}

0 个答案:

没有答案