【问题标题】:Confused about thread safe and race condition in C对 C 中的线程安全和竞争条件感到困惑
【发布时间】:2015-12-06 02:20:52
【问题描述】:

这本书说我们需要消除全局或静态数据以保证线程安全。我认为线程安全意味着程序中没有竞争条件。 但是,在以下示例中,它将本地名副其实的“Point pt_ptr”从非指针类型更改为指针类型“Point *pt_ptr”,以防止竞争条件。我注意到他使用“malloc”,这意味着他将在堆中创建一些东西。堆中的东西由所有线程共享......因为它创建了共享的东西,它可以防止数据竞争但它会是线程不安全的吗?

int main(void) {
  pthread_t tids[NUM_THREADS];
  int i;
  Point *pt_ptr;

  for (i= 0; i < NUM_THREADS; i++) {
    pt_ptr= malloc(sizeof(*pt_ptr));
    pt_ptr->x= i;
    pt_ptr->y= 3 * i + 2;
    pthread_create(&tids[i], NULL, print_point, pt_ptr);
  }

【问题讨论】:

  • 所以,是的,内存是共享的,所有线程都可以看到。然而,重要的部分是,如果该数据实际上是由多个线程访问的。如果不是 - 没有问题,如果您确实有多个线程访问数据,则可能有问题。所以你需要告诉我们更多。您的“由于它创建了共享的东西,因此可以防止数据竞争”似乎也很错误。
  • 全局变量简称为共享内存,但在这种情况下pt_ptr是不共享的,它作为新的私有内存分配给每个线程。

标签: c multithreading thread-safety


【解决方案1】:

只有当多个线程尝试访问相同的内存空间(例如变量)而没有一些线程安全机制(例如互斥锁或信号量)时,它才会是线程不安全的。它们用于提供一种阻塞机制,以便一个线程将坐下来“等待”,直到当前拥有的线程通过,此时第二个线程将能够访问/修改变量。

将它们视为 DMV 的号码,您必须等到您的号码被呼叫后才能获得服务。

【讨论】:

  • 因为for循环的每次迭代都会在堆中为指针pt_ptr创建一个新的内存空间,所以是安全的,对吧? @J.Murray
  • 您的示例使用一个单线程,因此您的 for 循环语句一次只会执行一个。通过 for 语句在每个循环中调用 malloc() 实际上每次都会分配一个新的内存块。所以,从本质上讲,每次循环你都在使用一个全新的项目。
【解决方案2】:

在这种情况下,循环的每次迭代都会调用malloc(),创建一个只传递给一个线程的新内存块。 (正如 J. Murray 正确指出的那样。)这些动态变量根本不是真正的全局变量。你可以改写:

int main(void)
{
  pthread_t tids[NUM_THREADS];

  for ( int i = 0; i < NUM_THREADS; i++) {
    Point * const pt_ptr = malloc(sizeof(*pt_ptr));
    assert(pt_ptr);  /* TODO: Handle the out-of-memory error. */
    pt_ptr->x= i;
    pt_ptr->y= 3 * i + 2;
    pthread_create(&tids[i], NULL, print_point, pt_ptr);
  }
  /* ... */
  return EXIT_SUCCESS;
}

该版本更清楚地表明pt_ptr 的每次迭代实际上都是一个单独的局部变量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-19
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    相关资源
    最近更新 更多