开发者

Object lock is not working for Thread Safety

I was testing thread-safety for better grasp and this is what I did :

I have a Type called ThreadSample which has two methods and this where locking is happening :

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);
       开发者_开发技巧 }
    }

Basically the idea is when doSomething() is called, it should lock the entire objects and other threads can even invoke anotherLife method since they are waiting for other threads to release the lock.

This is the logic to simulate lock-release :

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");
    }
}

As you can see in the code right below :

When Form is being initialized, a new Thread and ThreadSample are created. Then when user clicks on the button1, thread is started and the UIThread is reaching and invoking anotherLife which is not thread-safe at first.

Anyways, the output is :

  • There are two MessageBox shown at the same time.

What I was expecting is when the new Thread invokes doSomething(), it gets the lock of the object and UIThread waits for the lock to be released to be able to invoke anotherLife method.

Can some one explain why?

Thanks.


What I was expecting is when the new Thread invokes doSomething(), it gets the lock of the object and UIThread waits for the lock to be released to be able to invoke anotherLife method.

UIThread won't wait for a lock to be released before allowing anotherLife to proceed because anotherLife is not performing a lock. Both threads have to run into a lock statement (locking on the same object) in order to get the behavior you're looking for. Try modifying it to something like:

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


Well, lock(this) or lock(someThing) can be a bit of a misleading metaphor.

There is nothing being done 'to' this, but rather the argument to lock is used as a token. All threads accessing a specific resource must use the same token (object) to request access, otherwise your code is broken.

That is why frequently a helper object is used:

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

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

This scheme only works if all threads lock on myLock before changing myList.
It is considered a 'best practice` because it is not guaranteed that a List<> is safe to lock on.


Only your thread observes the lock

You need to change

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

to

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

Based on your code, it seems you think putting a lock on an object means that object can't be accessed by anything else. That is not the case. A lock on an object just means another lock may not be put on the object until the first lock is released.

You access the object from two places in your code, one in the thread and the other in the button event. You need a lock in both places.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜