C# threading - Lock Object

冷暖自知 提交于 2019-12-06 19:05:42

问题


I am trying to lock a "boxed" object in a c# app, is this not possible?

    class t
    {
        System.Object t_x = new object();

        public t(int p)
        {
            t_x = p;

        }

        public void w()
        {
            lock (t_x)
            {
                for (int i = 0; i < 4; i++)
                {

                    {
                        t_x = ((int)t_x) + 1;
                        Console.WriteLine(t_x);
                        Thread.Sleep(1000);
                    }
                }
            }
        }
    }

In another class I can start 2 threads:

        Thread b1 = new Thread(new ThreadStart(t1.w));
        b1.Start();
        Thread b2 = new Thread(new ThreadStart(t1.w));
        b2.Start();

However the portion is not locked. When I lock an arbitrary object (i.e. one created and not modified as object a=new object()) it locks well. Is boxing operation somehow "depromotes" my Object??


回答1:


You need to create a separate lock object. The problem is that you re-assign t_x inside the loop. Assuming thread b1 gets inside the loop before b2 gets to the lock statement, b2 will be allowed inside the lock statement because, by that time, t_x will be a new object that does not have a lock on it.




回答2:


No, you can't do this - the lock block is shorthand for the following:

try(Monitor.Enter(lockObject))
{
    //critical section
}
finally
{
    Monitor.Exit(lockObject)
}

The documentation for Monitor.Enter states, "Use Monitor to lock objects (that is, reference types), not value types. When you pass a value type variable to Enter, it is boxed as an object. If you pass the same variable to Enter again, it is boxed as a separate object, and the thread does not block"




回答3:


The lock (t_x) call boxes an integer as a temporary object. Each call to lock(t_x) creates a New object and locking is useless.

(Lock expects an object and creates a NEW temporary object from the integer)

Just create a seperate lock object like said above by Femaref.




回答4:


You have to use an extra object for the lock

object lockObj = new object();
public void foo()
{
    lock(lockObj)
    {
    //do stuff here
    }
}



回答5:


If you really want (need?) to lock on the object, you can use a kind of wrapper :

public class IntWrapper
{
    public int Value{get;set;}
}

Or if you need to stay more abstract :

public class ObjectWrapper
{
    public Object Value { get;set; }
}



回答6:


If you want to recognise when the data is loaded and also if the use tries to use it before then, you can do something like this:

Have a boolean flag like you mention, but use a separate object to lock before accessing it to prevent cross-thread race conditions.

When the user tries to use the data, if it is not loaded (check the variable) you can add another event handler to the worker RunWorkerCompleted event, that will immediately do what the user wants when the data is loaded.

Example:

public class MyClass
{
    private bool dataIsReady = false;
    private object locker = new object();
    BackgroundWorker worker;

    public void Begin()
    {
        worker = new BackgroundWorker();
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    }

    public void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        lock (locker)
        {
            dataIsReady = true;
        }
    }

    public void UseTriesToUseData()
    {
        lock (locker)
        {
            if (dataIsReady)
            {
                DoStuff();
            }
            else
            {
                this.worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(DoStuffCaller);
            }
        }
    }

    private void DoStuff()
    {
        // Do stuff with data.
    }

    private void DoStuffCaller(object sender, RunWorkerCompletedEventArgs e)
    {
        this.DoStuff();
    }
}


来源:https://stackoverflow.com/questions/1287356/c-sharp-threading-lock-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!