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