(1)三个线程协作打印ABCABCABC

(2)两个线程协作打印奇数偶数

--------------------------------

(1)三个线程协作打印ABCABCABC

(1.1)思路

并发编程核心是三大块:分工互斥同步

1)互斥

这道题并不涉及共享变量,所以不需要考虑互斥,首先排除。

2)同步

一眼就能看出这道题考的就是同步,那怎么同步呢?很容易想到的方法,就是每个线程打印前,等待别的线程通知;打印后,再去通知别的线程。
等待与唤醒,无非就是Object的wait、notify;

3)分工

就是考虑每个线程要做什么事情,需要哪些成员变量

每个线程需要两个Condition变量,一个condition用来等待上个线程通知,一个condition用来通知下个线程。

每个线程需要打印自己的字母,然后更改字母,通知下一个线程进行打印;

分析:

在生产者消费者中,生产者有2个条件变量,消费者两个条件变量,2个角色,一个两个条件变量即可;

在此中,printA、printB,printC线程各2个条件变量,3个角色,需要3个条件变量;

条件变量 + 线程互斥量来进行线程的同步,整体只需一个线程互斥量。

另外:线程互斥量也可以包含临界资源,此中的临界资源就是要打印的变量,因为线程中要修改该变量。

(1.2)分析

条件变量一般和线程互斥量共同作用来控制线程之间的协作;

pthread_cond_t类型;

pthread_cond_wait()函数;

pthread_cond_signal()函数;

pthread_mutex_t类型;

pthread_mutex_lock()函数;

pthread_mutex_unlock()函数;

(1.3)代码实现

#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";   //初始化=A,保证先打印A;即printA线程先启动;

//线程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);
}
 

//线程B
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);
}
 
 //线程C
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 <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;   //起始为偶数,说明先打印偶数,先启动偶数线程;
 /*

*  此中一个线程打印奇数,一个线程打印偶数,只有2个角色,就只有2个条件变量即可。

*/
// 打印奇数
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);
}