4

是否可以保证一个线程中的内存写入何时在使用pthreads 的其他线程中变得可见?

与 Java 相比,Java 语言规范有一个部分指定锁和内存的交互,这使得编写可移植的多线程 Java 代码成为可能。

是否有相应的 pthreads 规范?

当然,你总是可以让共享数据变得易变,但这不是我想要的。

如果这取决于平台,是否有事实上的标准?还是应该使用另一个线程库?

4

2 回答 2

8

POSIX 在4.11 Memory Synchronization中指定了内存模型:

应用程序应确保多个控制线程(线程或进程)对任何内存位置的访问受到限制,以便没有控制线程可以读取或修改内存位置,而另一个控制线程可能正在修改它。使用同步线程执行以及相对于其他线程同步内存的函数来限制此类访问。以下函数相对于其他线程同步内存:

  • 叉()
  • pthread_barrier_wait()
  • pthread_cond_broadcast()
  • pthread_cond_signal()
  • pthread_cond_timedwait()
  • pthread_cond_wait()
  • pthread_create()
  • pthread_join()
  • pthread_mutex_lock()
  • pthread_mutex_timedlock()
  • pthread_mutex_trylock()
  • pthread_mutex_unlock()
  • pthread_spin_lock()
  • pthread_spin_trylock()
  • pthread_spin_unlock()
  • pthread_rwlock_rdlock()
  • pthread_rwlock_timedrdlock()
  • pthread_rwlock_timedwrlock()
  • pthread_rwlock_tryrdlock()
  • pthread_rwlock_trywrlock()
  • pthread_rwlock_unlock()
  • pthread_rwlock_wrlock()
  • sem_post()
  • sem_timedwait()
  • sem_trywait()
  • sem_wait()
  • semctl()
  • semop()
  • 等待()
  • 等待进程()

pthread_once() 函数应为给定 pthread_once_t 对象的每个线程中的第一次调用同步内存。

如果互斥锁类型为 PTHREAD_MUTEX_RECURSIVE 并且调用线程已经拥有互斥锁,则 pthread_mutex_lock() 函数不需要同步内存。如果互斥锁类型为 PTHREAD_MUTEX_RECURSIVE 并且互斥锁的锁计数大于 1,则 pthread_mutex_unlock() 函数不需要同步内存。

除非另有明确说明,否则如果上述函数之一返回错误,则未指定调用是否导致内存同步。

应用程序可能允许多个控制线程同时读取一个内存位置。

于 2012-10-07T23:46:27.310 回答
0

我不知道 POSIX 线程提供了这样的保证。他们没有对线程共享对象进行原子访问的模型。如果是针对 POSIX 线程,唯一可以保证修改可见性的是使用某种锁。

现代 C、C11(可能还有 C++11)有一个模型来解决这类问题。当您假设一个线程所做的修改对另一个线程可见时,它具有线程和原子(栅栏和所有这些东西)为您提供确切的规则。

C11 的线程接口是 POSIX 线程的简化版本,功能较少。不幸的是,该线程接口的语义规范还很松散,基本上很多地方都缺少语义。但是 C11 接口和 POSIX 线程语义的组合可以让您很好地了解现代系统中的工作方式。

编辑:因此,如果您想保证内存同步,请使用 POSIX 提供的锁接口或进行原子操作。所有现代编译器都有提供这些的扩展,gcc 和家族(icc、opencc、clang)有例如一系列内置函数__sync...。Clang 它的最新版本也已经支持新的 C11_Atomic功能。还有一些可用的包装器为您提供接近_Atomic.

于 2012-10-07T20:54:43.417 回答