c # Проблема синхронизации потоков - PullRequest
0 голосов
/ 02 сентября 2011

Итак, я вижу забавный материал, играющий с потоками.

У меня есть метод, который запускает 2 потока и продолжает его жизнь, и я попытался сделатьследующее, чтобы обеспечить безопасность.

    bool CopyOk1 = false;
    bool CopyOk2 = false;
    new Thread(() => FirstMethod(tempList1, ref CopyOk1)).Start();
    new Thread(() => SecondMethod(tempList2, ref CopyOk2)).Start();
    var spinner = new SpinWait();
    while (!CopyOk1 || !CopyOk2)
        spinner.SpinOnce();

затем в обоих методах я начинаю со следующего

    private static void FirstMethod(List<T> templist, ref bool CopyOk)
    {
        var temp = new T[templist.Count];
        templist.CopyTo(temp);
        CopyOk = true;
        //moves on
    }

Я собираюсь скопировать переданный список, чтобы я мог его изменить и использоватьбезопасно внутри потоков как можно скорее, чтобы разблокировать поток вызывающего.

Моя проблема заключается в том, что во втором методе непредсказуемо между инициализацией массива и списком CopyTo базовый список каким-то образом изменяется каким-то образом.

Эти списки создаются внутри потока вызывающего и фактически не используются после запуска потоков, поэтому я абсолютно НЕТ представляю, как / почему это происходит.

Без сомнения, я делаю что-то не так, но мои навыки нубизма не дают мне увидеть, любая помощь приветствуется.

Ответы [ 4 ]

2 голосов
/ 02 сентября 2011

Вместо блокировки «templist» используйте глобальную блокировку. Затем защитите весь код, который изменяет список источников с той же блокировкой.

Кроме того, возможно, в стороне, но ожидание частичного завершения потока может быть выполнено более элегантно, то есть без использования цикла. Использование ManualResetEvent позволит вашему исходному потоку ожидать «что-то» в других потоках. Использование WaitOne блокирует поток до тех пор, пока в другом потоке не будет вызван Set ().

private object m_Lock = new object();
private ManualResetEvent m_ResetOne = new ManualResetEvent(false);
private ManualResetEvent m_ResetTwo = new ManualResetEvent(false);

(...)

new Thread(() => FirstMethod(tempList1)).Start();
new Thread(() => SecondMethod(tempList2)).Start();
m_ResetOne.WaitOne();
m_ResetTwo.WaitOne();

(...)

private void FirstMethod(List<T> templist)
{
    lock (m_Lock)
    {
        var temp = new T[templist.Count];
        templist.CopyTo(temp);
    }
    m_ResetOne .Set();
    //moves on
}
1 голос
/ 02 сентября 2011

Ничто в опубликованном вами коде не говорит о том, что вы делаете что-то не так. Проблема должна лежать в другом месте - скорее всего, как предположили комментаторы, в коде, который заполняет List1 / List2. Если вы также пользуетесь этим потоком, возможно, вы не ждете, пока этот поток завершит заполнение списков, прежде чем продолжить?

0 голосов
/ 02 сентября 2011

Вам нужен какой-то механизм синхронизации, чтобы предотвратить изменение List<T>. Мы не можем увидеть достаточно кода в текущем примере, чтобы гарантировать, что он не изменяется.

0 голосов
/ 02 сентября 2011

Попробуйте и проверьте поведение

private static void FirstMethod(List<T> templist, ref bool CopyOk)
{
    T[] temp;

    lock (templist)
    {
        temp = new T[templist.Count];
        templist.CopyTo(temp);
    }
    CopyOk = true;
    //moves on
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...