Разница между global / local / stati c Mutex? - PullRequest
5 голосов
/ 10 июля 2020

Мьютекс используется для предотвращения одновременного доступа двух или более потоков к одному и тому же ресурсу (файлу, переменной, ..). Это предотвращает возникновение состояния гонки.

Каждый поток имеет свой собственный стек. Это означает, что когда поток вызывает функцию, поток будет иметь уникальную копию локальных переменных, определенных в этой функции. Но если локальная переменная определена как static, будет создана только одна копия этой переменной, и эта копия будет доступна для всех потоков.

  • Означает ли это, что local NON- static мьютекс бесполезен?

  • Может ли быть полезен локальный мьютекс static? Может быть, для защиты локальной переменной static?

  • Каким образом определение мьютекса global как static имеет значение?

Ответы [ 3 ]

4 голосов
/ 10 июля 2020

Нестатистический c локальный мьютекс по-прежнему может быть полезен: если у вас есть основной поток, который создает другие потоки и ожидает их завершения sh, мьютекс может быть локальной переменной в основном потоке, и он передаст указатель на этот мьютекс другим потокам. Это работает только в том случае, если гарантировано, что основной поток переживет другие.

Если переменная мьютекса объявлена ​​как static внутри вашей функции потока, она будет совместно использоваться разными потоками, которые используют эту функцию, и они могут используйте его для синхронизации. Это потому, что static переменные имеют такое же время жизни, что и глобальные переменные (и только одна уникальная копия). Однако это работает только в том случае, если ваша библиотека потоковой передачи не требует вызова функции для инициализации мьютекса, поскольку не было бы подходящего места для этой инициализации.

Другой вариант - динамически выделить мьютекс или, что чаще всего, сделать его членом динамически выделяемой структуры. Затем вы можете передать указатель на мьютекс (или содержащую структуру) всем потокам, которые в нем нуждаются.

Что касается вашего последнего вопроса: определение глобальной переменной как static означает, что она видна только в текущем единица перевода. Это не влияет на его время жизни, поэтому будет работать аналогично нестатическим c глобальным переменным для этого варианта использования (при условии, что вам нужно получить к нему доступ только в одном файле. c).

1 голос
/ 10 июля 2020

Локальная функция обратного вызова потока бесполезна - мьютекс, который не используется совместно несколькими функциями, не имеет особого смысла. Однако вы можете сделать его локальным static для уменьшения беспорядка области / глобального пространства имен, а затем поделиться им между функциями с помощью указателей. Например, пусть основной поток создает его, а затем передает его различным потокам во время создания. Часто это наиболее разумно - иметь один поток, отвечающий за создание и очистку всех потоков и мьютексов и т. Д. c в проекте.

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

Термин «глобальный» сбивает с толку и плохо определен . Обычно это означает глобальный для всего проекта. Где как переменная, объявленная вне любой функции, имеет файловую область , но такая переменная может иметь внешнюю или внутреннюю связь. Внешнее значение «глобальный». Но если вы объявляете переменную области видимости файла static, она получает внутреннюю связь и видна только для файла. c, в котором она была объявлена. Это хорошо, потому что сокращает объем и предотвращает программирование спагетти с глобальными переменными.

0 голосов
/ 10 июля 2020

stati c in C означает, что он виден только в этом файле. Таким образом, если все функции, использующие stati c mutex , расположены в одном файле, то они будут использовать один и тот же мьютекс. Если к мьютексу осуществляется доступ из функций в нескольких файлах, он должен быть глобальным . Обычно у вас есть глобальная переменная состояния и связанный с ней глобальный мьютекс.

// in types.h
typedef struct {
  pthread_mutex_t lock;
  int val;
} state_t;


// in shared.h
extern state_t global_state;

// in code
#include "types.h"
#include "shared.h"

int foo() {
   pthread_mutex_lock(global_state.lock);
   global_state.val = STATE_FOO;
   pthread_mutex_unlock(global_state.lock);
}

Мьютекс на функцию не имеет смысла.

...