У меня есть функция, которая изменяет общий ресурс в моей многопоточной программе. Эта функция - единственное место, где потоки касаются общего ресурса, и это лишь небольшая часть общей работы каждого потока.
static int64_t
AddToSharedResource(volatile int64_t* value, int64_t to_add)
{
int64_t result = *value;
*value += to_add;
return result;
}
Я хотел сделать свое приложение потокобезопасным, поэтому я добавил простую блокировку мьютекса между инструкциями.
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static int64_t
AddToSharedResource(volatile int64_t* value, int64_t to_add)
{
pthread_mutex_lock(&lock);
int64_t result = *value;
*value += to_add;
pthread_mutex_unlock(&lock);
return result;
}
Это делает мою программу более чем в 10 раз медленнее, делая ее даже медленнее, чем однопоточная версия !
После прочтения немного больше, похоже, из-за реализации macOS, которая использует "честные" мьютексы вместо использования spinlocks , и что есть определенные компромиссы между реализациями, но этот случай является одним из случаев, которые работают плохо. Однако причина, по которой я написал код таким образом, заключается в том, что я уже написал программу на Win32 (где блокировка практически не повлияла на производительность), и я планирую также перенести функцию на Linux.
Есть ли способ сделать эту функцию поточно-ориентированной в macOS без создания огромного узкого места, или мне нужно изменить дизайн уровня платформы?