2010-12-09 2 views
1

Я тестирование потокобезопасности для лучшего схватывания, и это то, что я сделал:замок Объект не работает ниточный

У меня есть тип называется ThreadSample, который имеет два метода, и это, где блокировка происходит:

internal class ThreadTime 
    { 

     public void doSomething(string message) 
     { 
      lock (this) 
      { 
       DialogResult t = MessageBox.Show(message); 
       Thread.Sleep(2000); 
      } 
     } 

     public void anotherLife(string message) 
     { 
      MessageBox.Show("This is coming from anotherLife method and and current threadNumber is " + message); 
     } 
    } 

в принципе идея заключается в том, когда doSomething() называется, он должен блокировать целые объекты и другие потоки могут даже вызывать anotherLife метод, так как они ждут другие потоки, чтобы освободить фиксатор.

Это логика для имитации блокировки-релиз:

public partial class Form1 : Form 
{ 
    private ThreadTime time; 
    private Thread thread; 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     thread = new Thread(new ThreadStart(workerThread)); 
     time = new ThreadTime(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     thread.Start(); 
     //Thread.Sleep(1000); 
     time.anotherLife("Current thread is = " + "UI Thread"); 
    } 

    private void workerThread() 
    { 
     //time.doSomething("Current thread is = " + Thread.CurrentThread.ManagedThreadId); 
     time.doSomething("Worker Thread"); 
    } 
} 

Как вы можете видеть в коде прямо ниже:

Когда Form инициализируется новый Thread и ThreadSample созданы. Затем, когда пользователь нажимает на button1, начинается поток, и UIThread достигает и вызывает anotherLife, который сначала не является потокобезопасным.

В любом случае, выход:

  • Есть два MessageBox показано, в то же самое время.

То, что я ожидал, когда новая тема вызывает doSomething(), он получает блокировку объекта и UIThread ждет замок, чтобы быть освобожден, чтобы иметь возможность ссылаться на anotherLife метод.

Может кто-нибудь объяснить, почему?

Спасибо.

+3

Почему у вас есть тег java, когда это явно C#? И почему вы используете соглашения об именах Java в C#? – 2010-12-09 17:55:18

+0

То, как я читаю ваш вопрос, похоже, что у вас есть некорректная идея о том, как работают замки. Блокировка объекта - это всего лишь токен для синхронизации. Ничего не происходит с самим объектом блокировки. – 2010-12-09 17:57:23

ответ

5

То, что я ожидал, когда новая тема вызывает DoSomething(), он получает блокировку объекта и UIThread ждет замок, чтобы быть освобожден, чтобы иметь возможность вызвать метод anotherLife.

UIThread не будет ждать освобождения блокировки, прежде чем разрешить anotherLife действовать, потому что anotherLife не выполняет блокировку. Оба потока должны запускаться в операторе lock (блокировка на том же объекте), чтобы получить поведение, которое вы ищете. Попробуйте изменить его на что-то вроде:

public void anotherLife(string message) 
{ 
    lock (this) 
    { 
     MessageBox.Show("This is coming from anotherLife method and and current threadNumber is " + message); 
    } 
} 
1

Ну, lock(this) или lock(someThing) может быть немного вводящим в заблуждение метафоры.

Нечего делать «до» this, а аргумент lock используется как токен. Все потоки, обращающиеся к определенному ресурсу, должны использовать один и тот же токен (объект) для запроса доступа, иначе ваш код будет нарушен.

Именно поэтому часто используется вспомогательный объект:

private List<string> myList = ...; 
private object myLock = new object(); 

lock(myLock) 
{ 
    myList.Add("foo"); 
} 

Эта схема работает только тогда, когда все нити замок на myLock перед изменением myList.
Это считается «лучшей практикой», потому что не гарантируется, что список <> безопасен для блокировки.

1

только ваш поток отмечает замке

Вы должны изменить

private void button1_Click(object sender, EventArgs e) 
    { 
     thread.Start(); 
     //Thread.Sleep(1000); 
     time.anotherLife("Current thread is = " + "UI Thread"); 
    } 

в

private void button1_Click(object sender, EventArgs e) 
    { 
     thread.Start(); 
     //Thread.Sleep(1000); 
lock(time) 
{ 
     time.anotherLife("Current thread is = " + "UI Thread"); 
} 
    } 

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

Вы получаете доступ к объекту из двух мест в своем коде, один в потоке, а другой в событии кнопки. Вам нужен замок в обоих местах.

Смежные вопросы