我有一个以下简单的问题:我需要创建三个线程并在每个线程中执行某个操作。第一个帖子需要将100
添加到array[0]
并从101
中减去array[1]
,第二个帖子需要将200
添加到array[1]
并减去{来自201
的{1}}以及最后的第三个帖子需要将array[2]
添加到300
并从array[2]
中减去301
。
以下是正确的解决方案,但运行时间非常庞大。如果我使用一个线程执行此任务,则运行时间将少于1秒,但是三个线程将运行时间增加到大约10秒(+ - 2秒)。 问题是什么?我认为有三个线程的解决方案必须更快。可能是我以错误的方式使用互斥?
array[0]
答案 0 :(得分:5)
虽然互斥量带来了巨大的开销,但这并不是您放缓的原因。原因是互斥锁序列化执行。只有一个线程可以在任何时间点运行,因为只有一个线程可以保存互斥锁。所以你在实践中得到的是一个带有额外同步开销的串行执行。
您希望您的线程像这样运行(X
表示正在运行的线程)。
Thread1: |X|X|X|X|X|
Thread2: |X|X|X|X|X|
Thread3: |X|X|X|X|X|
但相反,你得到的是这样的:
Thread1: |X| | |X| | |X| | |X| | |X| | |
Thread2: | |X| | |X| | |X| | |X| | |X| |
Thread3: | | |X| | |X| | |X| | |X| | |X|
在每个时间段,只有一个线程运行。
有几种方法:
您可以按照每个线程专门访问数组的不同索引的方式对操作进行分区。这样就可以避免使用互斥锁。但是,这需要对您的解决方案进行全面的重新设计。
您可以使每个线程在数组的本地副本上工作,然后在单个线程上组合所有线程的结果。这样做要简单得多,因为您只需将数据复制到线程中,即可省去互斥锁。
您可以为每个数组索引使用互斥锁,但由于高内存和时间开销,这似乎有点极端,因为碰撞概率实际上非常低。
总而言之,使用选项1将产生最佳性能,但使用选项2将比串行版本产生显着的加速,而设计工作相对较少。选项3不明智。
答案 1 :(得分:2)
使用线程和互斥锁时,必须考虑开销。什么是开销?我会举个例子:
飞机比汽车快得多,但机场登机和安检线的开销使得汽车成为短途旅行的更好选择。
因此,使用pthread_create
,pthread_mutex_lock(&mutex);
和pthread_mutex_unlock(&mutex);
会产生开销,在某些情况下,它会使您的程序比无线程序更慢。