相关疑难解决方法(0)

互斥锁功能是否足够而没有易失性?

我和同事为在x86,x64,Itanium,PowerPC和其他10年历史的服务器CPU上运行的各种平台编写软件.

我们刚刚讨论了pthread_mutex_lock()... pthread_mutex_unlock()等互斥函数本身是否足够,或者受保护变量是否需要是volatile.

int foo::bar()
{
 //...
 //code which may or may not access _protected.
 pthread_mutex_lock(m);
 int ret = _protected;
 pthread_mutex_unlock(m);
 return ret;
}
Run Code Online (Sandbox Code Playgroud)

我担心的是缓存.编译器是否可以在堆栈或寄存器中放置_protected的副本,并在赋值中使用该陈旧值?如果没有,是什么阻止了这种情况发生?这种模式的变化是否易受攻击?

我假设编译器实际上并不理解pthread_mutex_lock()是一个特殊函数,所以我们只是受序列点保护吗?

非常感谢.

更新:好的,我可以看到一个趋势,答案解释了为什么不稳定是坏的.我尊重这些答案,但有关该主题的文章很容易在网上找到.我在网上找不到的,以及我问这个问题的原因,就是我如何保护我没有不稳定.如果上面的代码是正确的,那么缓存问题如何无懈可击?

c++ multithreading mutex volatile memory-barriers

39
推荐指数
3
解决办法
7299
查看次数

使用C/Pthreads:共享变量需要是不稳定的吗?

在C编程语言中,Pthreads作为线程库; 在线程之间共享的变量/结构是否需要声明为volatile?假设他们可能受到锁定或不受保护(可能是障碍).

pthread POSIX标准对此有任何发言权,是依赖于编译器还是不依赖于编译器?

编辑添加:感谢您的回答.但是,如果你使用锁,那该怎么办?如果你使用障碍物怎么办?或者使用比较和交换等原语直接和原子地修改共享变量的代码......

c multithreading pthreads

31
推荐指数
3
解决办法
2万
查看次数

互斥是否需要在pthreads之间同步一个简单的标志?

让我们假设我有一些工作线程如下:

while (1) {
    do_something();

    if (flag_isset())
        do_something_else();
}
Run Code Online (Sandbox Code Playgroud)

我们有几个帮助函数来检查和设置标志:

void flag_set()   { global_flag = 1; }
void flag_clear() { global_flag = 0; }
int  flag_isset() { return global_flag; }
Run Code Online (Sandbox Code Playgroud)

因此,线程继续do_something()在忙循环中调用,并且如果某些其他线程设置global_flag线程也调用do_something_else()(例如,可以通过从另一个线程设置标志来请求时输出进度或调试信息).

我的问题是:我是否需要做一些特殊的事情来同步对global_flag的访问?如果是,那么以便携方式进行同步的最小工作究竟是什么?

我试图通过阅读许多文章来解决这个问题,但我仍然不太确定正确的答案......我认为它是以下之一:

答:无需同步,因为设置或清除标志不会产生竞争条件:

我们只需要定义标志,volatile以确保每次检查时都从共享内存中读取它:

volatile int global_flag;
Run Code Online (Sandbox Code Playgroud)

它可能不会立即传播到其他CPU核心,但迟早会保证.

B:需要完全同步以确保在线程之间传播对标志的更改:

在一个CPU核心中设置共享标志不一定会让另一个核心看到它.我们需要使用互斥锁来确保通过使其他CPU上的相应缓存行无效来传播标志更改.代码如下:

volatile int    global_flag;
pthread_mutex_t flag_mutex;

void flag_set()   { pthread_mutex_lock(flag_mutex); global_flag = 1; pthread_mutex_unlock(flag_mutex); }
void flag_clear() { pthread_mutex_lock(flag_mutex); global_flag = 0; pthread_mutex_unlock(flag_mutex); }

int  flag_isset()
{
    int rc;
    pthread_mutex_lock(flag_mutex);
    rc …
Run Code Online (Sandbox Code Playgroud)

c synchronization pthreads

16
推荐指数
1
解决办法
6459
查看次数

pthread_mutex_lock是否包含内存栅栏指令?

这样做的pthread_mutex_lock调用pthread_mutex_unlock函数调用的存储栅栏/屏障指令?或者像compare_and_swap暗示那样的低级指令是否有内存障碍?

c gcc multicore pthreads

12
推荐指数
2
解决办法
5027
查看次数

C/C++编译器是否可以通过pthread库调用合法地在寄存器中缓存变量?

假设我们有以下代码:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

void guarantee(bool cond, const char *msg) {
    if (!cond) {
        fprintf(stderr, "%s", msg);
        exit(1);
    }
}

bool do_shutdown = false;   // Not volatile!
pthread_cond_t shutdown_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t shutdown_cond_mutex = PTHREAD_MUTEX_INITIALIZER;

/* Called in Thread 1. Intended behavior is to block until
trigger_shutdown() is called. */
void wait_for_shutdown_signal() {

    int res;

    res = pthread_mutex_lock(&shutdown_cond_mutex);
    guarantee(res == 0, "Could not lock shutdown cond mutex");

    while (!do_shutdown) {   // while loop guards against spurious wakeups …
Run Code Online (Sandbox Code Playgroud)

c c++ concurrency standards sequence-points

9
推荐指数
1
解决办法
1282
查看次数

遵循多线程环境中的指针

如果我有一些看起来像这样的代码:

typedef struct {
    bool some_flag;

    pthread_cond_t  c;
    pthread_mutex_t m;
} foo_t;

// I assume the mutex has already been locked, and will be unlocked
// some time after this function returns. For clarity. Definitely not
// out of laziness ;)
void check_flag(foo_t* f) {
    while(f->flag)
        pthread_cond_wait(&f->c, &f->m);
}
Run Code Online (Sandbox Code Playgroud)

C标准中是否有任何内容阻止优化器将check_flag重写为:

void check_flag(foo_t* f) {
    bool cache = f->flag;
    while(cache)
        pthread_cond_wait(&f->c, &f->m);
}
Run Code Online (Sandbox Code Playgroud)

换句话说,每次循环时生成的代码是否必须跟随f指针,或者编译器是否可以自由地取消引用?

如果它可以自由拉出来,有什么办法可以防止这种情况发生吗?我需要在某处撒一个volatile关键字吗?它不能是check_flag参数,因为我计划在这个结构中有其他变量,我不介意编译器这样优化.

可能我不得不诉诸:

void check_flag(foo_t* f) {
    volatile bool* cache …
Run Code Online (Sandbox Code Playgroud)

c multithreading pthreads c99 compiler-optimization

6
推荐指数
2
解决办法
238
查看次数

C - 可以通过不同的线程修改全局指针吗?

全局指针在线程之间是否存在范围?

例如,假设我有两个文件,file1.c和file2.c:

file1.c中:

uint64_t *g_ptr = NULL;

modify_ptr(&g_ptr) { 
    //code to modify g_ptr to point to a valid address 
}

read_from_addr() {
    //code which uses g_ptr to read values from the memory it's pointing to
}
Run Code Online (Sandbox Code Playgroud)

file2.c中:

function2A() {
    read_from_addr();
}
Run Code Online (Sandbox Code Playgroud)

所以我有threadA,它运行在file1.c中并执行modify_ptr(&g_ptr)和read_from_addr().然后threadB运行,它通过执行function2A()的file2.c运行.

我的问题是:threadB是否看到g_ptr被修改了?或者它仍然看到它指向NULL?

如果不是这样,那么指针是全局的意味着什么?如何确保在不同线程之间可以访问此指针?

如果我需要澄清任何事情,请告诉我.谢谢

c multithreading pointers

5
推荐指数
1
解决办法
3461
查看次数

dispatch_once是否在+ [NSObject initialize]内部过度杀伤?

如果我在里面创建一个单例+[NSObject initialize],我是否需要将我的代码放在一个dispatch_once块中?

static NSObject * Bar;
@implementation Foo
+ (void)initialize {
  if (self == [Foo class]) {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
      Bar = [NSObject new];
    });
  }
}
@end
Run Code Online (Sandbox Code Playgroud)

编辑

我很关心这个,因为我想确保所有线程都会看到我调用Bar之后设置的+[Foo initialize].文档说+[NSObject initialize]是线程安全的,但这是否意味着它是内存安全的?

concurrency objective-c objective-c-runtime grand-central-dispatch ios

5
推荐指数
2
解决办法
1162
查看次数

测试互斥锁之外的值:内存排序问题

我正在尝试减少代码需要执行的锁定量,并且遇到了一些关于pthread_mutex_lock如何处理其内存障碍的学术问题.为了使这个易于理解,假设互斥锁正在保护一个初始化后完全静态的数据字段,但我想将此设置推迟到第一次访问时.我想写的代码如下:

/* assume the code safely sets data to null at setup,
 * and the mutex is correctly setup 
 */
if (NULL == data) {
    pthread_mutex_lock(&lock);
    /* Need to re-check data in case it was already setup */
    if (NULL == data) 
        data = deferred_setup_fcn();
    pthread_mutex_unlock(&lock);
}
Run Code Online (Sandbox Code Playgroud)

我看到的可能问题是数据是在锁内设置的,但是在锁外读取.编译器是否可以跨互斥锁定调用缓存数据值?或者我是否必须插入适当的volatile关键字以防止这种情况发生?

我知道用pthread_once调用可以做到这一点,但我想避免使用另一个数据字段(锁已经存在保护相关字段).

指向POSIX线程函数调用内存排序的权威指南的指针也可以很好地工作.

c pthreads

4
推荐指数
1
解决办法
558
查看次数