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