这是一个简单的无锁实现,用于强制线程顺序执行。它使用一个原子状态变量,可以表示四种可能的状态:
-
working = 其中一个线程正在工作
-
ready_for_task1 = 轮到 task1 开始工作了
-
ready_for_task2 = 轮到 task2 开始工作了
-
ready_for_task3 = 轮到 task3 开始工作了
一般的想法是循环通过这些状态:
ready_for_task1 ->
working ->
ready_for_task2 ->
working ->
ready_for_task3 ->
working ->
ready_for_task1 ->
...
第一部分,定义状态,声明全局原子状态,并定义一个执行状态转换的守卫类。守卫的守卫构造函数将通过原子地检查其就绪状态并将状态切换为工作来“忙碌”等待。守卫析构函数会将状态设置为下一个任务的就绪状态。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <atomic>
enum State { ready_for_task1, ready_for_task2, ready_for_task3, working };
static std::atomic< State > state_;
class TransitionGuard {
public:
TransitionGuard(State start, State finish) : finish_(finish) {
State expecting = start;
while( !state_.compare_exchange_weak( expecting, working ) ) {
expecting = start;
asm("pause");
}
}
~TransitionGuard() {
state_.store( finish_ );
}
private:
const State finish_;
};
然后每个线程运行自己的循环,在各自的转换保护下打印它们的单词。
void * task1( void * data )
{
while( true ) {
TransitionGuard guard( ready_for_task1, ready_for_task2 );
printf( "Good" );
}
}
void * task2( void * data)
{
while( true ) {
TransitionGuard guard( ready_for_task2, ready_for_task3 );
printf( " Morning" );
}
return NULL;
}
void * task3( void * data)
{
while( true ) {
TransitionGuard guard( ready_for_task3, ready_for_task1 );
printf( " All\n" );
}
return NULL;
}
最后,您需要在创建线程之前初始化状态。
int main( int argc, const char ** argv )
{
state_ = ready_for_task1;
pthread_t thread1, thread2, thread3;
if( pthread_create( &thread1, NULL, task1, NULL ) )
{
fprintf( stderr, "thread1 failed to start\n" );
exit(EXIT_FAILURE);
}
if( pthread_create( &thread2, NULL, task2, NULL ) )
{
fprintf( stderr, "thread2 failed to start\n" );
exit(EXIT_FAILURE);
}
if( pthread_create( &thread3, NULL, task3, NULL ) )
{
fprintf( stderr, "thread3 failed to start\n" );
exit(EXIT_FAILURE);
}
pthread_join( thread1, NULL );
pthread_join( thread2, NULL );
pthread_join( thread3, NULL );
fprintf( stderr, "threads joined. exiting.\n" );
exit(EXIT_SUCCESS);
}