Передаются ли объекты Mutex по ссылке? - PullRequest
1 голос
/ 20 октября 2011

Я создаю несколько объектов из класса и использую определенную функцию из этих классов для запуска потоков.Теперь класс, содержащий функцию-член, из которой эти объекты построены, имеет статический закрытый член Mutex.Я передаю этот статический член конструкторам, и внутри каждого конструктора переданный Mutex (предположительно по ссылке) назначается другому локальному члену.

Если я буду использовать каждый из этих локальных членов Mutex для обеспечения безопасности потоков, смогу ли я этого добиться?Я рассчитываю на факт, независимо от того, сколько существует различных экземпляров объекта, содержащего функцию Thread, поскольку все они ссылаются на один и тот же объект Mutex, безопасность потока гарантируется при правильном использовании.

Ниже приведен фрагмент кода для представления идеи:

Class ThreadClass
{
 private Mutex myCopyOfMutex;
public ThreadClass(Mutex _globalMutex)
{
 myCopyOfMutex = _globalMutex;
}
public ThreadFunction()
{

// Wait until it is safe to enter.
myCopyOfMutex.WaitOne();
// critical code

// Release the Mutex.
 myCopyOfMutex.ReleaseMutex();

}
}

Class MotherClass
{
  private static Mutex mut = new Mutex();

  ThreadClass one = new ThreadClass(mut); // first instance
  Threadclass two = new ThreadClass(mut); // second instance

// Assign the Thread function to run on separate Thread

}

Ответы [ 4 ]

3 голосов
/ 20 октября 2011

Да, это будет работать. Нет, это не передается по ссылке.

Существует важное различие между передачей a эталона и передачей по эталоном .

Когда вы передаете ссылочный тип методу, он обычно передается как ссылка :

SomeMethod(mutex);

Чтобы передать параметр по ссылке , используйте ключевое слово ref:

SomeMethod(ref mutex);

Параметр в сигнатуре метода также должен быть объявлен с использованием ключевого слова ref:

public void SomeMethod(ref Mutex mutex) {

Передача переменной по ссылке означает, что вы передаете ссылку на переменную, а не копию ссылки, которая содержится в переменной. Затем метод может изменить саму переменную, а не только объект, на который указывает ссылка.

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

1 голос
/ 20 октября 2011

да, мьютекс передается по ссылке, поскольку это тип класса, а не тип структуры

1 голос
/ 20 октября 2011

(Ответ полностью переписан, старый ответ внизу)

Обычно System.Threading.Mutex используется для межпроцессного взаимодействия.Если вы просто хотите синхронизировать свои потоки в рамках одного и того же процесса, использование Mutex с полным весом является излишним.Вы можете использовать любой объект с оператором lock:

Class ThreadClass
{
    // static is important, this way the object is shared among all
    // class instances
    private static object myMutex = new object();

    public ThreadFunction()
    {
        // Wait until it is safe to enter.
        lock(myMutex)
        {
            // critical code
        }
        // the mutex is automatically released after leaving the block.
    }
}

Class MotherClass
{
    ThreadClass one = new ThreadClass(); // first instance
    Threadclass two = new ThreadClass(); // second instance

    // Assign the Thread function to run on separate Thread
}

Преимущество lock -approach заключается в возможности быстрого возврата и безопасности исключений (представьте, что произойдет, если критический код выдает исключение;но посмотрите на статью Эрика Липперта об исключениях при блокировке ).

Если метод целом является критическим, и не более критических методовв классе вы можете сделать это еще проще:

Class ThreadClass
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    public ThreadFunction()
    {
        // critical code
    }
}

Class MotherClass
{
    ThreadClass one = new ThreadClass(); // first instance
    Threadclass two = new ThreadClass(); // second instance

    // Assign the Thread function to run on separate Thread
}

(Старый ответ здесь сохраняется для согласованности)

Все экземпляры класса передаются по ссылке в C #.Если ваш Mutex является классом (например, это System.Threading.Mutex), он будет автоматически передан по ссылке.

Смотрите здесь для получения дополнительной информации.


Исправление:
Как правильно говорит @Guffa, вы не передаете экземпляр класса по ссылке, а ссылку на экземпляр класса по значению (если не используете * 1035)* ключевое слово).На самом деле это почти то же самое.Разница в том, что изменения в переданной ссылке не видны за пределами вызываемого абонента.

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

Из вашего брифинга я предполагаю, что вы используете Mutex для синхронизации доступа к общим ресурсам.

Mutex - это управляемый эталонный тип, который под прикрытием использует неуправляемый мьютекс из Win32. Чтобы ответить на ваш вопрос, да, это тип ссылки.

Но ваш вопрос заставляет меня задуматься над двумя пунктами

  1. Почему вы беспокоитесь о рекомендации?

Мой совет таков: если вы беспокоитесь о том, что один и тот же экземпляр Mutex может использоваться совместно, тогда создайте именованный Mutex (проверьте перегрузку конструктора для Mutex). Операционная система под прикрытием обеспечит синхронизированный доступ с именем Mutex.

  1. Почему вы хотите, чтобы экземпляр Mutex был статическим?

Мой совет здесь заключается в том, что статические переменные выделяются JIT в специальной куче, связанной с AppDomain. Это называется кучей загрузчика. Эта куча загрузчика никогда не будет собирать мусор, если вы не выгрузите / перезагрузите AppDomain. Поэтому я хочу сказать, что если вы используете Mutex в качестве статического члена, то, скорее всего, у вас будет много дескрипторов мьютекса.

...