Подтвердить что ты не робот

С# threading - Объект блокировки

Я пытаюсь заблокировать объект "boxed" в приложении С#, это невозможно?

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

В другом классе я могу запустить 2 потока:

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

Однако часть не заблокирована. Когда я блокирую произвольный объект (т.е. Один созданный и не модифицированный как объект a = новый объект()), он хорошо блокируется. Является ли операция бокса каким-то образом "депромотами" моего объекта?

4b9b3361

Ответ 1

Вам нужно создать отдельный объект блокировки. Проблема в том, что вы повторно назначаете t_x внутри цикла. Предполагая, что поток b1 попадает внутрь цикла до того, как b2 попадает в оператор блокировки, b2 будет разрешен внутри оператора блокировки, потому что к этому времени t_x будет новым объектом, который не имеет блокировки на нем.

Ответ 2

Нет, вы не можете этого сделать - блок блокировки является сокращением для следующего:

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

Документация для Monitor.Enter гласит: "Использовать монитор для блокировки объектов (то есть типов ссылок), а не типов значений. Когда вы передайте переменную типа значения в Enter, она помещается как объект. Если вы снова передаете одну и ту же переменную Enter, она помещается в отдельный объект, а поток не блокирует"

Ответ 3

Вы должны использовать дополнительный объект для блокировки

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

Ответ 4

Блокировка (t_x) вызывает целое число как временный объект. Каждый вызов блокировки (t_x) создает новый объект и блокировка бесполезна.

(Lock ожидает объект и создает НОВЫЙ временный объект из целого числа)

Просто создайте отдельный объект блокировки, как указано выше, Femaref.

Ответ 5

Если вы действительно хотите (нужно?) блокировать объект, вы можете использовать своего рода обертку:

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

Или, если вам нужно оставаться более абстрактным:

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

Ответ 6

Если вы хотите узнать, когда данные загружены, а также если использование пытается использовать его до этого времени, вы можете сделать что-то вроде этого:

Имейте логический флаг, как вы упомянули, но используйте отдельный объект для блокировки перед его доступом, чтобы предотвратить условия гонки в поперечном потоке.

Когда пользователь пытается использовать данные, если он не загружен (проверьте переменную), вы можете добавить другой обработчик события рабочего рабочего RunWorkerCompleted, который немедленно сделает то, что пользователь хочет, когда данные будут загружены.

Пример:

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