c - 关于 pthread_mutex_lock() 函数的使用,哪一项是正确的?
问题描述
我正在学习如何通过多线程使用全局变量,但我现在有一个问题:关于pthread_mutex_lock()
和pthread_mutex_unlock()
.
function1 或 function2 中的用法正确吗?如果两者都不是,如何正确使用?
我当时只是修改了数组中的一个元素。比如改变后thread1
会AllSensorInfoArray[2][66].sensorType
改变thread1
,AllSensorInfoArray[2][67].sensorType
现在thread2可以改变AllSensorInfoArray[2][66].sensorType
。也就是说,不允许多个线程同时修改AllSensorInfoArray[2][66].sensorType
。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t AllSensorMutex;
void *function1(void *arg)
{
int t = 0, i = 0;
/*
some codes
*/
pthread_mutex_lock(&AllSensorMutex);
for (t = 0; t < 100; t++)
{
AllSensorInfoArray[i][t].sensorType = allData[2+t];
}
pthread_mutex_unlock(&AllSensorMutex);
/*
some codes
*/
}
void *function2(void *arg)
{
/*
some codes
*/
int t = 0, i = 0;
for (t = 0; t < 100; t++)
{
pthread_mutex_lock(&AllSensorMutex);
AllSensorInfoArray[i][t].sensorType = allData[2+t];
pthread_mutex_unlock(&AllSensorMutex);
}
/*
some codes
*/
}
int main(void)
{
while(pthread_mutex_init(&AllSensorMutex, NULL))
{
printf("(%s) write mutex init error!\n", __FUNCTION__);
sleep(1);
}
pthread_t thread1;
pthread_t thread2;
int ret = pthread_create(&thread1, NULL, function1, NULL);
if (ret != 0)
{
printf("(%s) failed to create a pthread, return error code : %d.\n", __FUNCTION__, ret);
exit(-1);
}
ret = pthread_create(&thread2, NULL, function2, NULL);
if (ret != 0)
{
printf("(%s) failed to create a pthread, return error code : %d.\n", __FUNCTION__, ret);
exit(-1);
}
while (1)
{
sleep(1);
}
}
解决方案
Correct is usage in function1 or function2?
Both are equally correct, and will work. The first one is "better" for this particular case.
The first one, which takes the mutex for the duration of the loop is more efficient, because there is less overhead (of locking and unlocking the mutex). It is best suited for things like copying data.
The second one, which takes the mutex for the duration of accessing each element, is better suited when the modification is more complicated and may take some time (relatively speaking), and you only need to access that one element. However, then you should only take the mutex for the modification itself, and not for the entire computation (or, say, sensor reading):
for (i = 0; i < sensor_count; i++) {
value = read_sensor(i);
pthread_mutex_lock(&mutex);
sensor_reading[i] = value;
pthread_mutex_unlock(&mutex);
}
instead of pthread_mutex_lock(&mutex); sensor_reading[i] = read_sensor(i); pthread_mutex_unlock(&mutex);
, because this latter would just hold the mutex while reading the sensor, blocking other threads' access to the array for the duration of the read_sensor(i)
call for no sensible reason.
Simple assignment or arithmetic on the array element is not 'slow', and therefore the first function is the recommended pattern here.
In general, the pattern
for (i = 0; i < N; i++) {
pthread_mutex_lock(&mutex);
/* Do something */
pthread_mutex_unlock(&mutex);
}
only releases the mutex for a short duration, and depending on the pthreads implementation, it may not be long enough for any other thread to grab the mutex, even if they were already blocking/waiting on the mutex (in a pthread_mutex_lock(&mutex) call). It is not wrong or an error, though, it just works the same as
pthread_mutex_lock(&mutex);
for (i = 0; i < N; i++) {
/* Do something */
}
pthread_mutex_unlock(&mutex);
and is less efficient than this latter form, because the former does (N
-1) extra pthread_mutex_lock() and pthread_mutex_unlock() calls, with no guarantees of any benefits of doing so.
推荐阅读
- javascript - Discord.js 权限
- python - 您是否应该在运行代码时需要在 virtualenv 中才能访问已安装的依赖项?
- azure - 如何使用 OAuth2 从 Azure AD 为数百万客户端获取唯一访问令牌
- reactjs - 如何给出边界半径反应引导下拉菜单
- python-3.x - Python .format() 没有产生所需的输出
- java - 如何使用未找到但已枚举的密钥?(安卓工作室)
- python - Django 最佳实践——在执行业务逻辑时确保原子性
- google-apps-script - 当我想将 GAS 项目作为附加组件发布时,触发器的类型是否仅限于一种?
- rust - 克隆 &[u32] 到 [u32]
- c++ - 为什么我收到一条错误消息,因为我没有在 Arduino 的范围内声明变量?