Многопоточная блокировка, веселые времена (тренировка в середине) - PullRequest
2 голосов
/ 24 октября 2011

Вот вопрос, о котором спорит моя учебная группа:

(g) Рассмотрим следующий код C #:

public class Demo {
    private static readonly object a = new object();
    private static readonly object b = new object();

    public static void Main (string[] args) {
        Demo d = new Demo();
        Task t1 = Task.Factory.StartNew(d.g);
        Task t2 = Task.Factory.StartNew(d.h);
        t2.Wait();
        t1.Wait();
    }

    private void g() {
        lock (a) {
            lock (b) {
                Console.Write("G");
            }
        }
    }

    private void h() {
        lock (b) {
            lock (a) {
                Console.Write("H");
            }
        }
    }
}

Это многопоточная программа, поэтому различные исполнения могутдают разные результаты.Поставьте галочку рядом с полным выводом, который может выдать программа.(Последний выбор означает отсутствие вывода.) Вывод Ответ

Вывод ------- Возможно?

GH  
HG  
G   
H   
(nothing)

Что мы думаем:

GH будетвыход, если t1 заблокирован b, прежде чем t2 заблокирован b.

(ничего) будет выходом, если t1 заблокирован a, а затем t2 заблокирован b, потому что это вызовет тупиквывод, если t1 заблокировал b, а затем, пока t1 все еще удерживал блокировку на b, t2 запустился, потому что t2.wait ожидал бы, пока t1 не завершит свою работу.или HG.Однако один из нас запускал код 200 000 раз, и иногда он получал HG ... Я не понимаю

Я просто не уверен в этих ответах.Что вы все думаете?Любая помощь с благодарностью!

Ответы [ 4 ]

0 голосов
/ 24 октября 2011

HG может произойти, потому что нет гарантии того, когда новый поток начнет выполняться.После создания Task t2 операционная система может сначала запустить ее, а затем вернуться и запустить t1.

0 голосов
/ 24 октября 2011

Я думаю, что единственный способ получить только G или только H - завершить обе функции, но программа завершается до того, как консоль сбросит вторую букву.

0 голосов
/ 24 октября 2011

Если вы когда-либо получаете одну букву, это означает, что одному потоку удалось получить обе блокировки. Это также означает, что он сможет снять обе блокировки, а другая нить завершится успешно - и распечатать другое письмо. Исходя из этого рассуждения, GH и HG являются возможными выходами. Также возможно попадание в тупик, где поток 1 удерживает один замок, а поток 2 - другой.

0 голосов
/ 24 октября 2011

Нет абсолютно никаких гарантий, что g() будет запущен раньше h().Как я понимаю, StartNew() на самом деле не запускает задачу, а ставит ее в очередь для следующего доступного потока.

...