【Linux】多线程利用条件变量打印AB,ABC,奇偶数

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/bible_reader/article/details/94843701

多线程利用条件变量打印AB,ABC,奇偶数

1、条件变量

条件变量是多线程同步的一种方式。

2、两个线程打印ABAB

#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#define NUM_THREADS     2

pthread_cond_t Aready = PTHREAD_COND_INITIALIZER;  // A是否ready的条件
pthread_cond_t Bready = PTHREAD_COND_INITIALIZER;  // B是否ready的条件
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
string nextchar = "A";

void* printerA(void*)
{
    for (int i = 0; i < 10; i++) {
        pthread_mutex_lock(&mutex);
        while (nextchar != "A") {
            pthread_cond_wait(&Aready, &mutex);
        }
        cout << nextchar;
        nextchar = "B";
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&Bready);
    }
    pthread_exit((void*) 1);
}

void* printerB(void*)
{
    for(int i = 0; i < 10; i++) {
        pthread_mutex_lock(&mutex);
        while (nextchar != "B") {
            pthread_cond_wait(&Bready, &mutex);
        }
        cout << nextchar;
        nextchar = "A";
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&Aready);

    }
    pthread_exit((void*) 2);
}

int main ()
{
   int rc;
   int i;
   pthread_t threads[NUM_THREADS];
   pthread_attr_t attr;
   void *status;


   // 初始化并设置线程为可连接的(joinable)
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   pthread_create(&threads[0], NULL, printerA, NULL);
   pthread_create(&threads[1], NULL, printerB, NULL);

   // 删除属性,并等待其他线程
   pthread_attr_destroy(&attr);
   for( i=0; i < NUM_THREADS; i++ ){
      rc = pthread_join(threads[i], &status);
      if (rc){
         cout << "Error:unable to join," << rc << endl;
         exit(-1);
      }
      cout << "Main: completed thread id :" << i ;
      cout << "  exiting with status :" << status << endl;
   }

   cout << "Main: program exiting." << endl;
   pthread_exit(NULL);
}
                      

3、三个线程打印ABCABC

方法1:

#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#define NUM_THREADS     3

pthread_cond_t Aready = PTHREAD_COND_INITIALIZER;
pthread_cond_t Bready = PTHREAD_COND_INITIALIZER;
pthread_cond_t Cready = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
string nextchar = "A";

void* printerA(void*)
{
    for (int i = 0; i < 10; i++) {
        pthread_mutex_lock(&mutex);
        while (nextchar != "A") {
            pthread_cond_wait(&Aready, &mutex);
        }
        cout << nextchar;
        nextchar = "B";
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&Bready);
    }
    pthread_exit((void*) 1);
}

void* printerB(void*)
{
    for(int i = 0; i < 10; i++) {
        pthread_mutex_lock(&mutex);
        while (nextchar != "B") {
            pthread_cond_wait(&Bready, &mutex);
        }
        cout << nextchar;
        nextchar = "C";
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&Cready);

    }
    pthread_exit((void*) 2);
}


void* printerC(void*)
{
    for (int i = 0; i < 10; i++) {
        pthread_mutex_lock(&mutex);
        while (nextchar != "C") {
            pthread_cond_wait(&Cready, &mutex);
        }
        cout << nextchar;
        nextchar = "A";
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&Aready);
    }
    pthread_exit((void*) 1);
}


int main ()
{
   int rc;
   int i;
   pthread_t threads[NUM_THREADS];
   pthread_attr_t attr;
   void *status;


   // 初始化并设置线程为可连接的(joinable)
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   pthread_create(&threads[0], NULL, printerA, NULL);
   pthread_create(&threads[1], NULL, printerB, NULL);
   pthread_create(&threads[2], NULL, printerC, NULL);

   // 删除属性,并等待其他线程
   pthread_attr_destroy(&attr);
   for( i=0; i < NUM_THREADS; i++ ){
      rc = pthread_join(threads[i], &status);
      if (rc){
         cout << "Error:unable to join," << rc << endl;
         exit(-1);
      }
      cout << "Main: completed thread id :" << i ;
      cout << "  exiting with status :" << status << endl;
   }

   cout << "Main: program exiting." << endl;
   pthread_exit(NULL);
}
                       

方法2:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

#define NUM_OF_CHARACTER 3

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

static int current_id = 0;

void* worker_thread(void *arg)
{
    int thread_id = *(int *)arg;
    for(int i=0; i<10; ++i){
        pthread_mutex_lock(&mutex);
        while(thread_id != current_id)
            pthread_cond_wait(&cond, &mutex);
        printf("%c", 'A'+thread_id);
        current_id = (current_id + 1) % NUM_OF_CHARACTER;
        pthread_mutex_unlock(&mutex);
        pthread_cond_broadcast(&cond);
    }
}

int main()
{
    int thread_id[NUM_OF_CHARACTER] = {0, 1, 2};
    pthread_t tids[NUM_OF_CHARACTER];
    for(int i=0; i<NUM_OF_CHARACTER; ++i)
        pthread_create(&tids[i], NULL, worker_thread, (void *)(thread_id+i));
    for(int i=0; i<NUM_OF_CHARACTER; ++i)
        pthread_join(tids[i], NULL);

    return 0;
}

4、两个线程打印奇偶数

#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#define NUM_THREADS     2

pthread_cond_t Oddready = PTHREAD_COND_INITIALIZER;  // 奇数ready
pthread_cond_t UnOddready = PTHREAD_COND_INITIALIZER;  // 偶数ready
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int i = 0;

// 打印奇数
void* printerOdd(void*)
{
    for (int index = 0; index < 10; index++) {
        pthread_mutex_lock(&mutex);
        while (i % 2 == 0) {
            pthread_cond_wait(&Oddready, &mutex);  // 当前是偶数的话,等待奇数ready条件满足
        }
        cout << "printOdd " << i << " ";
        i++;
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&UnOddready);
    }
    pthread_exit((void*) 1);
}

void* printerUnOdd(void*)
{
    for(int index = 0; index < 10; index++) {
        pthread_mutex_lock(&mutex);
        while (i % 2 != 0) {
            pthread_cond_wait(&UnOddready, &mutex); // 当前是奇数,等待偶数ready条件满足
        }
        cout << "printUnodd " << i << " ";
        i++;
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&Oddready);  // 打印完偶数后,将条件变量“奇数ready” 置为true
    }
    pthread_exit((void*) 2);
}

int main ()
{
   int rc;
   int i;
   pthread_t threads[NUM_THREADS];
   pthread_attr_t attr;
   void *status;


   // 初始化并设置线程为可连接的(joinable)
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   pthread_create(&threads[0], NULL, printerOdd, NULL);
   pthread_create(&threads[1], NULL, printerUnOdd, NULL);

   // 删除属性,并等待其他线程
   pthread_attr_destroy(&attr);
   for( i=0; i < NUM_THREADS; i++ ){
      rc = pthread_join(threads[i], &status);
      if (rc){
         cout << "Error:unable to join," << rc << endl;
         exit(-1);
      }
      cout << endl;
      cout << "Main: completed thread id :" << i ;
      cout << "  exiting with status :" << status << endl;
   }

   cout << "Main: program exiting." << endl;
   pthread_exit(NULL);
}
             

5、3个线程,一个线程打印1、2、3,第二个线程打印4、5、6,第三个线程打印7、8、9,第一个线程打印10、11、12,以此类推...


#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#define NUM_THREADS     3

pthread_cond_t ready = PTHREAD_COND_INITIALIZER;  // 线程ready
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  // 条件变量ready的互斥锁
pthread_mutex_t i_mutex = PTHREAD_MUTEX_INITIALIZER;  //  全局变量i的互斥锁
int i = 0;  // 全局计数
int state = 0; // 全局进程状态ready标记,0 表示线程1ready,1 表示线程2 ready,2 表示线程3 ready

// 周期性地打印数字i, i + 1, i + 2
void printer(int thread_id)
{
    pthread_mutex_lock(&i_mutex);
    cout << "thread-" << thread_id << endl;
    for (int index = 0; index < 3; index++) {

        cout << i + 1 << " ";
        i++;
    }
    cout << endl;
    pthread_mutex_unlock(&i_mutex);
}

void* printer(void* arg)
{
    int thread_id = *(int* )arg;
    for(int index = 0; index < 10; index++) {
        pthread_mutex_lock(&mutex);
        while (thread_id % 3 != state) {
            pthread_cond_wait(&ready, &mutex); // 如果thread_id % 3 != state,则对应的线程需要继续等待ready条件满足
        }
        printer(thread_id);
        state = (state + 1) % 3;  // 修改对应的线程ready标记
        pthread_mutex_unlock(&mutex);
        pthread_cond_broadcast(&ready);  // 某一个线程打印完毕后,设置state值,并通知其他所有线程,其他所有线程按照state的值,检查是否自己等待的ready条件是否满足
    }

    pthread_exit((void*) 1);  // 每一个线程的返回值设置为1;
}

int main ()
{
   int rc;
   int i;
   int thread_ids[] = {0, 1, 2};
   pthread_t threads[NUM_THREADS];
   pthread_attr_t attr;
   void *status;


   // 初始化并设置线程为可连接的(joinable)
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   // 创建3个线程
   for( i=0; i < NUM_THREADS; i++ ){
      rc = pthread_create(&threads[i], NULL, printer, (void*)(thread_ids + i));
      if (rc){
         cout << "create thread falied: " << rc << endl;
         exit(-1);
      }
   }


   // 删除属性,并等待其他线程
   pthread_attr_destroy(&attr);
   for( i=0; i < NUM_THREADS; i++ ){
      rc = pthread_join(threads[i], &status);
      if (rc){
         cout << "Error:unable to join," << rc << endl;
         exit(-1);
      }
      cout << endl;
      cout << "Main: completed thread id :" << i ;
      cout << "  exiting with status :" << status << endl;
   }

   cout << "Main: program exiting." << endl;
   pthread_exit(NULL);
}
                       

猜你喜欢

转载自blog.csdn.net/bible_reader/article/details/94843701
今日推荐