【问题标题】:atomic load/save on c struct (gcc) questionsc struct (gcc) 问题的原子加载/保存
【发布时间】:2016-07-11 23:01:15
【问题描述】:

尝试我的运气来实现无锁单链表。

typedef _Atomic struct _node
  {
    void *data;
    struct _node *next;
  } Node;

这是否使 _Atomic 结构的所有成员也都是原子的?

void add_head ( Linked_list* list, void* data )
{
  if ( debugging )
  {
      printf ( "%s\n", __func__ );
  }
  Node *node = ( Node* ) calloc ( 1, sizeof (Node ) );
  //init_node_mutex(node);
  //lock_node_mutex(node);
  atomic_exchange ( &node->next, NULL );
  atomic_exchange ( &node->data, data );

  if ( list->head == NULL )
  {
      Node* the_tail = atomic_load ( &list->tail );
      //  lock_node_mutex ( the_tail );
      atomic_exchange ( &node->next, NULL );
      atomic_compare_exchange_weak ( &list->tail, the_tail, node );

      //unlock_node_mutex ( the_tail );

  }
  else
  {

      Node* the_next = atomic_load ( &node->next );
      // lock_node_mutex ( the_next );
      atomic_compare_exchange_weak ( &node->next, the_next, list->head );
      // unlock_node_mutex ( the_next );
  }

  Node* the_head = atomic_load ( & list->head );
  //lock_node_mutex ( the_head );
  atomic_store ( &list->head, node );
  atomic_store ( &list->current, node );
  //unlock_node_mutex ( the_head );
  //unlock_node_mutex(node);
  atomic_fetch_add ( &list->size, 1 );
}

atomic_load 和 atomic_store 的用法是否正确?

【问题讨论】:

  • 在 C11 标准中,第 §6.5.2.3 节 结构和联合成员(对于 .-> 运算符)¶5 说 访问成员对原子结构或联合对象的访问会导致未定义的行为。97) 并且脚注 97 说 例如,如果在一个线程中访问整个结构或联合与访问成员发生冲突,则会发生数据竞争从另一个线程,其中至少一个访问是修改。可以使用分配给原子对象或从原子对象分配的非原子对象安全地访问成员。

标签: c gcc struct atomic gcc6


【解决方案1】:

好的,我曾考虑过是将其发布为“评论”还是“答案”,但我将在这里破产。

我的直觉在向我尖叫:“您执行的单个操作是否是“原子的”并不重要,因为您连续执行许多操作以完成你最终想要做什么。即使这些单独的步骤是“原子的”,整个操作也不是。

“原子”操作是一种使用专用机器指令的操作,例如 x86 上的 LOCK 前缀或 big-iron 上的“比较和交换”指令,以执行 单个操作,这样没有其他CPU(或内核)会干扰该单个操作。

但是,你不能在“单条指令”中做你想做的事,不管是不是原子的。

因此,我诚挚地建议您现在放弃您目前的课程,将那些“互斥”调用放回原处,并删除“原子”。您的代码(以及所有此类代码......)需要这些互斥锁。在我看来,你是在死胡同里追一只白兔。

(顺便说一下,“互斥”操作有时会很好地利用这些“原子指令”,因此它们的效率可能比您担心的要高。)

【讨论】:

    【解决方案2】:

    除了@MikeRobinson 的评论之外,我还要补充一点,虽然您的代码是“无锁”的,因为它不包含任何显式使用锁,但现在(有点讽刺的是)不再是线程安全的。编写无锁代码非常困难。我建议通读this 以鸟瞰世界,然后阅读this 以获取一些细节或this book 的第7 章(使用C++)。您可以随时查看Boost.LockFree 的来源以获得灵感。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 2016-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多