相关疑难解决方法(0)

使用pthread互斥锁保护变量是否保证它也不会被缓存?

考虑一个简单的(在我的情况下是全局)变量:

int i;
Run Code Online (Sandbox Code Playgroud)

在某处访问此变量

pthread_mutex_lock(i_mutex);
if(i == other value) {
  do_something();
}
pthread_mutex_unlock(i_mutex);
Run Code Online (Sandbox Code Playgroud)

另一个线程i 在保持时更新i_mutex.编译器可以缓存值,i所以我没有得到最近的值?一定i是不稳定的?

c pthreads

33
推荐指数
2
解决办法
6718
查看次数

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

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

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

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

c multithreading pthreads

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

假设没有"并发访问",安全地将内存块"借出"给C中的另一个线程

问题

我想在一个线程中分配内存,并安全地 "释放"指向另一个线程的指针,以便它可以读取该内存.

我正在使用一种翻译成C语言的高级语言.高级语言有线程(未指定的线程API,因为它是跨平台的 - 见下文)并支持标准的C多线程原语,如原子比较交换,但它没有真正记录(没有用法示例).这种高级语言的限制是:

  • 每个线程执行一个事件处理无限循环.
  • 每个线程都有自己的本地堆,由一些自定义分配器管理.
  • 每个线程都有一个"输入"消息队列,可以包含来自任意数量的不同其他线程的消息.
  • 传递队列的消息是:
    1. 对于固定类型的消息
    2. 使用复制

现在,对于大型(不希望复制)或可变大小(我认为数组大小是类型的一部分)消息,这是不切实际的.我想发送这样的消息,这里是我想要实现它的大纲:

  • 消息(请求回复)可以存储"有效负载"内联(复制,固定限制总值大小),或指向发送方堆中数据的指针
  • 消息内容(发送者堆中的数据)由发送线程拥有(分配和释放)
  • 接收线程在完成消息内容时向发送线程发送确认
  • "发送"线程在发送之后不得修改消息内容,直到收到(ack).
  • 应该永远是对内存并行读访问被写入,写之前完成.这应该由消息队列work-flow保证.

我需要知道如何确保这没有数据竞争.我的理解是我需要使用内存栅栏,但我不完全确定哪一个(ATOMIC_RELEASE,...)以及循环中的位置(或者我是否需要任何内容​​).


便携性考虑因素

因为我的高级语言需要跨平台,所以我需要得到答案:

  • Linux,MacOS以及可选的Android和iOS
    • 使用pthreads原语来锁定消息队列:pthread_mutex_initpthread_mutex_lock+pthread_mutex_unlock
  • 视窗
    • 使用Critical Section Objects来锁定消息队列:InitializeCriticalSectionEnterCriticalSection+LeaveCriticalSection

如果它有帮助,我假设以下架构:

  • 用于Windows/Linux/MacOS的英特尔/ AMD PC架构(?).
  • 适用于iOS和Android的未知(ARM?)

并使用以下编译器(您可以假设所有这些编译器的"最近"版本):

  • Windows上的MSVC
  • Linux上的铿锵声
  • Xcode在MacOS/iOS上
  • 适用于Android的CodeWorks for Android

到目前为止,我只在Windows上构建,但是当应用程序完成后,我希望以最少的工作将其移植到其他平台.因此,我试图从一开始就确保跨平台兼容性.


试图解决方案

这是我假设的工作流程:

  1. 读取队列中的所有消息,直到它为空(仅当它完全为空时才阻塞).
  2. 在这里叫一些"记忆围栏"?
  3. 读取消息内容(消息中指针的目标),并处理消息.
    • 如果消息是"请求",则可以处理该消息,并将新消息缓冲为"回复".
    • 如果消息是"回复",则可以释放原始"请求"的消息内容(隐式请求"确认").
    • 如果消息是"回复",并且它本身包含指向"回复内容"的指针(而不是"内联回复"),那么也必须发送"回复确认".
  4. 在这里叫一些"记忆围栏"?
  5. 将所有缓冲的消息发送到适当的消息队列中. …

c multithreading thread-safety nim-lang

21
推荐指数
1
解决办法
597
查看次数

使用Boost进行进程间读写器锁定

在解释如何使用Boost实现读/写锁时,这个线程是金牌.它似乎相对简单,我真的很喜欢它,但它似乎也使用一个非命名的锁,我需要一个进程间解决方案(不需要是可移植的,可以只有Windows).

有没有办法进行进程间shared_mutex?我看到有一个,named_mutex但我不能让它与shared_lock其他锁一起工作.

任何指针都表示赞赏.

[编辑]

与此同时,我遇到了这个几乎击中头部钉子的线程.我有两个问题:

  1. 它没有显示完整的代码(我猜我需要使用,named_upgradable_mutex但我不太确定)和
  2. 我不喜欢修改后的"编写器"的答案,它不使用在析构函数中解锁的现成类,而是使用互斥锁上的3个原始调用序列.

仍然欢迎评论或好的解决方案.

c++ boost boost-interprocess

7
推荐指数
1
解决办法
8532
查看次数

互斥锁定和解锁功能如何防止CPU重新排序?

据我所知,函数调用充当编译器障碍,但不作为CPU障碍.

教程说明如下:

获取锁意味着获取语义,而释放锁意味着释放语义!其间的所有内存操作都包含在一个漂亮的小屏障三明治中,防止任何不希望的内存重新排序跨越边界.

我假设上面的引用是关于CPU重新排序而不是编译器重新排序.

但我不明白互斥锁和解锁如何导致CPU赋予这些函数获取和释放语义.

例如,如果我们有以下C代码:

pthread_mutex_lock(&lock);
i = 10;
j = 20;
pthread_mutex_unlock(&lock);
Run Code Online (Sandbox Code Playgroud)

上面的C代码被翻译成以下(伪)汇编指令:

push the address of lock into the stack
call pthread_mutex_lock()
mov 10 into i
mov 20 into j
push the address of lock into the stack
call pthread_mutex_unlock()
Run Code Online (Sandbox Code Playgroud)

现在是什么阻止了CPU重新排序mov 10 into i以及mov 20 into j 上方call pthread_mutex_lock()或下方call pthread_mutex_unlock()

如果它是call阻止CPU进行重新排序的指令,那么为什么我引用的教程使它看起来像是互斥锁和解锁函数来阻止CPU重新排序,为什么我引用的教程没有说任何函数调用会阻止CPU重新排序吗?

我的问题是关于x86架构.

c x86 assembly mutex memory-barriers

1
推荐指数
2
解决办法
549
查看次数