【问题标题】:Protect a double var without using mutex在不使用互斥锁的情况下保护双变量
【发布时间】:2012-02-21 05:07:58
【问题描述】:

你好!!

我有一个在 linux 中运行的 c ap,它是一个 POSIX 多线程应用程序, 在线程 1 中,我以这种方式设置全局变量:

Pthread_mutex_lock(&Mutex1); 
for(idx=0;idx<1000;idx++)
{
      Data1[idx].doubleval = idx * 100.0 * anothervar  ;
}//for 
Pthread_mutex_unlock(&Mutex1); 

在 thread2 中,我以这种方式获取全局变量:

Pthread_mutex_lock(&Mutex1); 
for(idx=0;idx<1000;idx++)
{
     doublexxx = Data1[idx].doubleval ;
     DoSomething(doublexxx) ;
}//for 
Pthread_mutex_unlock(&Mutex1); 

现在,假设我不想在我的 ap 中使用 Mutex,如果 thread1 正在设置 Data1[33].doubleval 而 thread2 正在读取 Data1[33].doubleval ,那么 Data1[33].doubleval 会很奇怪吗价值 ?我的意思是,例如,double var 有 4 个字节,而 thread1 正在设置 Data1[33].doubleval 前 2 个字节,而不是完成后 2 个字节,此时 thread2 正在尝试读取 Data1[33].doubleval ....可能吗?

如果可能的话,我该如何保护双变量而不会出现这种问题? 互斥锁很好用,我只是想知道是否有另一种方法来保护双变量 哪个 thread1 正在其中写入,至少 thread2 尝试从同一个 var 中读取 将等待 4 个字节的 double var 完成!!!

【问题讨论】:

  • 只需使用互斥体,您就不必担心。为什么要不择手段地制造不必要的问题?
  • 说真的;如果您不想锁定,那么您不应该使用线程。
  • 谢谢,我的应用程序使用了太多线程,我想尽快运行,我不知道 mutex_lock 效果如何,实际上所有互斥锁都使用在一个小的内存 strcpy 块中,但我仍然被告知要让它运行得更快....谢谢大家的热情回复!

标签: c multithreading gcc mutex


【解决方案1】:

是否可以读取“部分写入”的值取决于大量因素(例如目标系统和对齐方式),并且绝对不可移植。例如,假设这段代码在 16 位 CPU 上运行,并在软件中模拟了浮点支持。

即使使用互斥体,第二个线程的行为仍然是不确定的,因为它不知道它是在第一个线程写入数据之前还是在第一个线程写入数据之后读取了数据。

我怀疑您的设计存在更高级别的问题 - 也许您应该使用条件变量让第二个线程等到第一个线程写入。

我还怀疑您询问删除互斥锁的原因是为了提高可伸缩性/性能。例如,一个线程使用数组的一部分,而另一个线程修改同一个数组的完全不同的部分。如果这是您问题背后的原因,那么解决方案取决于您的场景 - 它可能就像使用多个锁一样简单(每个数组区域一个互斥锁,每个条目最多一个互斥锁),但可能意味着实现一个“阅读器/writer" 锁(这样就允许多个线程同时从数组中读取,只要没有其他线程正在写入)。

【讨论】:

  • 谢谢...线程1在无限循环中写入数据,线程2也在无限循环中读取数据,我的目标是获得更高的性能,我只关心线程2不会得到奇怪的值,如果那样的话值是正确的值不管thread1写快还是慢,然后我不会使用互斥锁...因为thread2只需要一个合理的值尽快,我最害怕的是thread2读取了一个不合理的值,就像我说的2字节写在 thread1 中,没有在后面的 2 个字节中完成......
【解决方案2】:

要担心的问题不是在写入过程中读取值;我不知道有什么系统可以做到这一点。问题是您的第二个线程的行为将是未定义的,因为您不知道它是在第一个线程写入给定内存部分之前还是之后读取。如果没有互斥体或功能等效的东西,就无法获得明确定义的行为。

【讨论】:

  • 字撕裂肯定会发生在 Alpha 处理器上。在 x86 CPU 上,我相信它只会发生在未对齐的访问中,假设编译器没有做任何有趣的事情。 (例如,GCC 有时会在读取一个值后将其写回内存,即使代码没有更改该值。这可能会导致另一个线程的写入丢失。)
  • 假设 thread2 总是读取一个 global double var g1 而 thread1 总是写入,这两个线程都处于无限循环中,如果 g1 现在是 1.55,并且 thread1 将执行 g1=1.66,如果 thread2 是将在没有互斥锁的情况下同时读取 g1,如果我可以确保 g1 必须 =1.55 或 1.66,没有其他值可能,那么我想我会避免互斥锁!
猜你喜欢
  • 1970-01-01
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多