是否有必要使 pthread_mutex_t 变量可变?
Is it necessary to make pthread_mutex_t variable volatile?
在java中,我们通常将锁变量设为最终静态,这样它就只存在一个副本(虽然我记得读过,即使是静态变量也可以复制到两个方法的调用堆栈中!)
但是我正在处理C和数据的同步。我已经声明了一个 pthread_mutex_t 变量,N 个线程将在该变量上锁定以访问公共资源。
我不确定这个变量是否是重复证明(java 中静态变量的问题,它可能会或可能不会被复制到两种方法的调用堆栈中)。因为如果它们被编译器复制,那么我担心锁定可能无法工作。那么我们是否需要像 "volatile" 这样更激进的访问修饰符来使它真正成为单数?
简答:没有。
如果您声明的变量是全局变量,那么将只有一个(独立于 volatile 限定符)。 volatile 通常用于可能在中断(微控制器)或另一个线程的上下文中发生变化的变量,而不是锁本身。
看起来volatile在C和Java中的含义不同。看看:https://barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword
C's volatile keyword is a qualifier that is applied to a variable when
it is declared. It tells the compiler that the value of the variable
may change at any time--without any action being taken by the code the
compiler finds nearby.
不仅没有必要; 不允许。 pthread_mutex_...
函数的参数具有类型 pthread_mutex_t *
并且需要指向 pthread_mutex_t
对象的有效指针。指向 volatile pthread_mutex_t
的指针不会像指向 const pthread_mutex_t
的指针那样自动转换,因为它在需要不合格指针的地方不可用。您可以通过强制转换来转换它,但这样您就会有违反函数约定的未定义行为。
要更加强调为什么需要这样做,您可以查看以下示例:
如果你这样写:
void parallel_function(){
//Example function, this doesn't exist, but it is good to let you understand
pthread_mutex_is_free(&lock);
doStuff();
}
然后 pthread_mutex_is_free 会在锁定之前检查互斥体是否空闲。
这里有一个问题,问题出在编译器优化上,因为对他来说,代码是从单线程执行的,所以,它可以选择跳过这个检查(互斥量是免费的),因为他看到之前设置了那个变量因为是免费的,而且永远不会改变,所以它将永远是免费的,这是无用的,所以在编译代码中跳过了。
所以使用 Volatile,强制编译器避免这种检查,基本上告诉它期待这个变量神奇地改变,从而避免静态优化。
在java中,我们通常将锁变量设为最终静态,这样它就只存在一个副本(虽然我记得读过,即使是静态变量也可以复制到两个方法的调用堆栈中!)
但是我正在处理C和数据的同步。我已经声明了一个 pthread_mutex_t 变量,N 个线程将在该变量上锁定以访问公共资源。
我不确定这个变量是否是重复证明(java 中静态变量的问题,它可能会或可能不会被复制到两种方法的调用堆栈中)。因为如果它们被编译器复制,那么我担心锁定可能无法工作。那么我们是否需要像 "volatile" 这样更激进的访问修饰符来使它真正成为单数?
简答:没有。 如果您声明的变量是全局变量,那么将只有一个(独立于 volatile 限定符)。 volatile 通常用于可能在中断(微控制器)或另一个线程的上下文中发生变化的变量,而不是锁本身。
看起来volatile在C和Java中的含义不同。看看:https://barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword
C's volatile keyword is a qualifier that is applied to a variable when it is declared. It tells the compiler that the value of the variable may change at any time--without any action being taken by the code the compiler finds nearby.
不仅没有必要; 不允许。 pthread_mutex_...
函数的参数具有类型 pthread_mutex_t *
并且需要指向 pthread_mutex_t
对象的有效指针。指向 volatile pthread_mutex_t
的指针不会像指向 const pthread_mutex_t
的指针那样自动转换,因为它在需要不合格指针的地方不可用。您可以通过强制转换来转换它,但这样您就会有违反函数约定的未定义行为。
要更加强调为什么需要这样做,您可以查看以下示例:
如果你这样写:
void parallel_function(){
//Example function, this doesn't exist, but it is good to let you understand
pthread_mutex_is_free(&lock);
doStuff();
}
然后 pthread_mutex_is_free 会在锁定之前检查互斥体是否空闲。 这里有一个问题,问题出在编译器优化上,因为对他来说,代码是从单线程执行的,所以,它可以选择跳过这个检查(互斥量是免费的),因为他看到之前设置了那个变量因为是免费的,而且永远不会改变,所以它将永远是免费的,这是无用的,所以在编译代码中跳过了。 所以使用 Volatile,强制编译器避免这种检查,基本上告诉它期待这个变量神奇地改变,从而避免静态优化。