简体   繁体   English

多线程自旋锁?

[英]Multithreaded spin lock?

My daemon initializes itself in four different threads before it starts doing its things.我的守护进程在它开始做它的事情之前在四个不同的线程中初始化它自己。 Right now I use a counter which is incremented when a thread is started and decremented when it is finished.现在我使用一个计数器,它在线程启动时递增,在线程完成时递减。 When the counter hits 0 I call the initialization finished callback.当计数器达到 0 时,我调用初始化完成回调。

Is this the preferred way to do it, or are there better ways?这是首选的方法,还是有更好的方法? I'm using POSIX threads ( pthread ) and I just run a while cycle to wait for the counter to hit 0.我正在使用 POSIX 线程( pthread ),我只是运行一段while循环来等待计数器达到 0。

Edit: pthread_barrier_* functions are not available on my platform although they do seem to be the best choice.编辑: pthread_barrier_*函数在我的平台上不可用,尽管它们似乎是最好的选择。

Edit 2: Not all threads exit.编辑 2:并非所有线程都退出。 Some initialize and then listen to events.一些初始化然后监听事件。 Basically the thread needs to say, "I'm done initializing".基本上线程需要说,“我完成了初始化”。

A barrier is what you need.你需要一个障碍。 They were created for that, when you need to "meet up" at certain points before continuing.它们是为此而创建的,当您需要在某些时间点“见面”然后再继续时。 See pthread_barrier_*请参见 pthread_barrier_*

pthread_join is the preferred way to wait for pthreads. pthread_join 是等待 pthreads 的首选方式。

That sounds... weird.这听起来很奇怪。 Shouldn't you just be using pthread_join() to wait for the threads to complete?你不应该只是使用pthread_join()来等待线程完成吗? Maybe I don't understand the question.也许我不明白这个问题。

Rather than spinning, use the pthread mutex/condvar primitives.与其旋转,不如使用 pthread mutex/condvar 原语。 I'd suggest a single mutex to protect both the count of threads outstanding, and the condvar.我建议使用单个互斥锁来保护未完成的线程数和 condvar。

The main loop looks like this:主循环如下所示:

acquire mutex
count=N_THREADS;
start your N threads
while (1) {
  if (count==0) break;
  cond_wait(condvar);
}
release mutex

And when each thread is ready it would do something like this:当每个线程准备就绪时,它会执行以下操作:

acquire mutex
count--
cond_signal(condvar)
release mutex

(EDIT: I have assumed that the threads are to keep going once they have done their initialisation stuff. If they are to finish, use pthread_join as others have said.) (编辑:我假设线程一旦完成初始化工作就会继续运行。如果他们要完成,请使用pthread_join就像其他人所说的那样。)

As Klas Lindbäck pointed out in his answer, joining threads is a preferred way to go.正如 Klas Lindbäck 在他的回答中指出的那样,加入线程是 go 的首选方式。 In case your threads are not exiting (ie are part of the reusable pool etc.), the logic sounds good.如果您的线程没有退出(即是可重用池的一部分等),逻辑听起来不错。 The only thing is that using counter without any synchronisation is dangerous.唯一的问题是在没有任何同步的情况下使用计数器是危险的。 You have to use either mutex with condition or atomic integer.您必须使用带条件的互斥锁或原子 integer。 I'd recommend using mutex + condition if you don't want to spin on atomic counter in the thread that waits for initialisation to finish.如果您不想在等待初始化完成的线程中旋转原子计数器,我建议您使用互斥锁 + 条件。

So, what happens if one thread finishes initialization before any of the others begin?那么,如果一个线程在其他线程开始之前完成初始化会发生什么?

So one way to do it所以一种方法

  1. initialize an atomic counter to 0将原子计数器初始化为 0
  2. when each thread is done with init, increment counter and retrieve the value atomically.当每个线程都使用 init 完成时,递增计数器并以原子方式检索值。 If you use GCC, you can use __sync_add_and_fetch()如果你使用 GCC,你可以使用 __sync_add_and_fetch()
  3. If the retrieved counter value < N_threads, block on a pthread condition variable.如果检索到的计数器值 < N_threads,则阻塞 pthread 条件变量。
  4. If the retrieved counter value == N_threads, init phase is done, signal the condition and continue.如果检索到的计数器值 == N_threads,则初始化阶段完成,发出条件信号并继续。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM