在C ++中同步线程

时间:2018-10-24 10:05:36

标签: c++ multithreading

我有三个线程-线程1打印“良好”,线程2打印“早晨”,线程3打印“全部”。如何使用这些线程在屏幕上连续打印“ Good Morning All”?

2 个答案:

答案 0 :(得分:0)

对于一个,您只是在浪费资源。

但是,假设您确实需要此功能来完成比仅打印单词更重要的事情,这是一个建议:

创建3个互斥锁(pthread_mutex)

pthread_mutex_t m_Good, m_Morning, m_all;
pthread_mutex_init(&m_Good, NULL);
pthread_mutex_init(&m_Morning, NULL);
pthread_mutex_init(&m_All, NULL);

锁定最后两个互斥锁

pthread_mutex_lock(&m_Morning);
pthread_mutex_lock(&m_All);

在第一个线程中打印其消息,然后解锁第二个互斥锁。

while(true){
    if(pthread_mutex_lock(&m_Good)==0){
         printf("GOOD ");
         pthread_mutex_unlock(&m_Morning);
         pthread_mutex_lock(&m_Good);
    }
}
  • 第二个线程打印消息,锁定其互斥锁并解锁第三个
  • 第三个线程打印其消息,解锁第一个互斥锁并锁定第三个互斥锁

答案 1 :(得分:0)

这是一个简单的无锁实现,用于强制顺序执行线程。它使用一个原子状态变量,可以表示四个可能的状态:

  • 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 ->
...

第一部分,定义状态,声明全局原子状态,并定义执行状态转换的保护类。通过自动检查其就绪状态并将状态切换为工作状态,后卫的后卫构造函数将“忙于”等待。 Guard析构函数会将状态设置为下一个任务的就绪状态。

#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);
}