C++多執行緒筆試程式設計題
一
子執行緒迴圈 10 次,接著主執行緒迴圈 100 次,接著又回到子執行緒迴圈 10 次,接著再回到主執行緒又迴圈 100 次,如此迴圈50次,試寫出程式碼。
2017.2.11日更新:
之前寫這幾段程式碼忘記對mutex和condition呼叫pthread_destroy()!
程式碼如下:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#define TEST_TIMES_LIMIT 3
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
typedef enum {MAIN_THREAD, WORKER_THREAD}SWITCH_THREAD;
SWITCH_THREAD target;
void* worker_thread(void* arg)
{
for(int test=0; test<TEST_TIMES_LIMIT; ++test){
pthread_mutex_lock(&mutex);
while(target != WORKER_THREAD)
pthread_cond_wait(&cond, &mutex);
//pthread_mutex_unlock()函式和主執行緒中一樣,都可以放在這裡
//因為下面並不存在race condition,所以放在這裡縮小了臨界區,但效率並無提高
printf("worker thread:>\n");
for(int i=1; i<=10; ++i)
printf("%d ", i);
printf("\n");
target = MAIN_THREAD;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
}
void main_thread()
{
for(int test=0; test<TEST_TIMES_LIMIT; ++test){
pthread_mutex_lock(&mutex);
while(target != MAIN_THREAD)
pthread_cond_wait(&cond, &mutex);
printf("main thread:>\n");
for(int i=1; i<=100; ++i)
printf("%d ", i);
printf("\n\n");
target = WORKER_THREAD;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
}
int main()
{
target = WORKER_THREAD;
pthread_t tid;
int ret = pthread_create(&tid, NULL, worker_thread, NULL);
assert(ret != -1);
main_thread();
pthread_join(tid, NULL);
return 0;
}
二
編寫一個程式,開啟3個執行緒,這3個執行緒的ID分別為A、B、C,每個執行緒將自己的ID在螢幕上列印10遍,要求輸出結果必須按ABC的順序顯示;如:ABCABC….依次遞推。
方法一:採用條件變數和互斥鎖
#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;
}
注意我的執行緒id是用單獨的陣列儲存並傳遞給執行緒的,如果直接使用for迴圈中的&i,那麼執行緒區域性thread_id會隨著i改變。
方法二:使用原子操作(推薦)
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#define TEST_TIMES 10
#define NUM_OF_CHARACTERS 3
static volatile int counter = 0;
void* worker_thread(void *arg)
{
int thread_id = *(int *)arg;
for(int i=0; i<TEST_TIMES; ++i){
while(counter % NUM_OF_CHARACTERS != thread_id);
printf("%c", 'A'+thread_id);
__sync_fetch_and_add(&counter, 1);
}
}
int main()
{
int thread_id[NUM_OF_CHARACTERS] = {0, 1, 2};
pthread_t tid[NUM_OF_CHARACTERS];
for(int i=0; i<NUM_OF_CHARACTERS; ++i)
pthread_create(&tid[i], NULL, worker_thread, (void *)(thread_id+i));
for(int i=0; i<NUM_OF_CHARACTERS; ++i)
pthread_join(tid[i], NULL);
return 0;
}
三
讀者寫者問題
這也是一個非常經典的多執行緒題目,題目大意如下:有一個寫者很多讀者,多個讀者可以同時讀檔案,但寫者在寫檔案時不允許有讀者在讀檔案,同樣有讀者讀時寫者也不能寫。
做到這道題為之,我已經不耐煩POSIX執行緒API了,我要拿起我的老本行C++來做了。
#include <iostream>
#include <thread>
#include <condition_variable>
#include <unistd.h>
class rwlock {
public:
rwlock() : writer_(0), reader_(0), active_(0) {}
public:
void read_lock() {
std::unique_lock<std::mutex> lock(lk_);
++reader_; //讀鎖用的時候說明要讀,我們在函式實現中增加讀者數目
while(active_ < 0 || writer_ > 0) //(1)有人已經佔用資源(2)當前有優先順序更高的寫者執行緒
rcond_.wait(lock);
--reader_;
++active_; //注意: 讀鎖是++
}
void write_lock() {
std::unique_lock<std::mutex> lock(lk_);
++writer_; //同理
while(active_ != 0) //注意注意,是不等於0
wcond_.wait(lock);
--writer_;
active_ = -1; //寫鎖是直接賦為-1
}
void unlock() {
std::unique_lock<std::mutex> lock(lk_);
if(active_ > 0){ //解鎖讀鎖
if(--active_ == 0) //因為有多個讀者,直到讀者數目為0,才喚醒wait狀態的寫者,表示所有讀者讀完了,寫者可以上了
wcond_.notify_one();
}
else{ //到此處說明是解鎖寫鎖
active_ = 0; //直接賦值為0
if(writer_ > 0) //優先寫
wcond_.notify_one();
else if(reader_ > 0)
rcond_.notify_all(); //可多個同時讀
}
}
private:
std::mutex lk_;
std::condition_variable wcond_;
std::condition_variable rcond_;
unsigned int writer_;
unsigned int reader_;
int active_;
};
void worker_1(const std::shared_ptr<rwlock>& rl)
{
while(1){
rl->write_lock();
std::cout<<"writing start."<<std::endl;
sleep(5);
std::cout<<"write done"<<std::endl;
rl->unlock();
sleep(5);
}
}
void worker_2(const std::shared_ptr<rwlock>& rl)
{
while(1){
rl->read_lock();
std::cout<<"Jinping Xi reading"<<std::endl;
sleep(1);
std::cout<<"Jinping Xi read done"<<std::endl;
rl->unlock();
}
}
void worker_3(const std::shared_ptr<rwlock>& rl)
{
while(1){
rl->read_lock();
std::cout<<"Keqiang Li reading"<<std::endl;
sleep(1);
std::cout<<"Keqiang Li read done"<<std::endl;
rl->unlock();
}
}
int main()
{
std::shared_ptr<rwlock> rl(new rwlock());
std::thread th1(worker_1, rl);
std::thread th2(worker_2, rl);
std::thread th3(worker_3, rl);
th1.join();
th2.join();
th3.join();
return 0;
}
由於lock_guard不能直接使用.wait(),所以這裡用的是unique_lock。它們基本功能是一樣的,後者功能更豐富一些。
相關文章
- C++ 多執行緒程式設計總結C++執行緒程式設計
- Linux C++ 多執行緒程式設計LinuxC++執行緒程式設計
- 程式設計思想之多執行緒與多程式(4):C++ 中的多執行緒程式設計執行緒C++
- 多執行緒程式設計,處理多執行緒的併發問題(執行緒池)執行緒程式設計
- 多執行緒程式設計執行緒程式設計
- c++多執行緒程式設計:C2672C++執行緒程式設計
- JavaScript多執行緒程式設計JavaScript執行緒程式設計
- Boost多執行緒程式設計執行緒程式設計
- UNIX多執行緒程式設計執行緒程式設計
- 多執行緒程式設計(轉)執行緒程式設計
- .NET多執行緒程式設計(1):多工和多執行緒 (轉)執行緒程式設計
- 【C/C++多執行緒程式設計之十】pthread執行緒私有資料C++執行緒程式設計thread
- VC多執行緒 C++ 多執行緒執行緒C++
- 使用執行緒池優化多執行緒程式設計執行緒優化程式設計
- iOS多執行緒程式設計:執行緒同步總結iOS執行緒程式設計
- .NET多執行緒程式設計(3):執行緒同步 (轉)執行緒程式設計
- [短文速讀 -5] 多執行緒程式設計引子:程式、執行緒、執行緒安全執行緒程式設計
- python 多執行緒程式設計Python執行緒程式設計
- Python多執行緒程式設計Python執行緒程式設計
- GCD 與多執行緒程式設計GC執行緒程式設計
- IOS多執行緒程式設計:概述iOS執行緒程式設計
- C#多執行緒程式設計C#執行緒程式設計
- linux 多執行緒程式設計Linux執行緒程式設計
- 多執行緒程式設計ExecutorService用法執行緒程式設計
- 29. 多執行緒程式設計執行緒程式設計
- C++ Builder 多執行緒程式設計技術經驗談C++UI執行緒程式設計
- .NET多執行緒程式設計(4):執行緒池和非同步程式設計 (轉)執行緒程式設計非同步
- 程式設計思想之多執行緒與多程式(3):Java 中的多執行緒程式設計執行緒Java
- 多執行緒程式設計基礎(一)-- 執行緒的使用執行緒程式設計
- c++ 程式通用多執行緒單例設計 c++ web 框架設計經驗談C++執行緒單例Web框架
- Java多執行緒程式設計筆記10:單例模式Java執行緒程式設計筆記單例模式
- Java多執行緒程式設計筆記2:synchronized同步方法Java執行緒程式設計筆記synchronized
- 多執行緒程式設計總結:一、認識多執行緒本質執行緒程式設計
- java執行緒的筆試題Java執行緒筆試
- [02] 多執行緒邏輯程式設計執行緒程式設計
- Java多執行緒程式設計基礎Java執行緒程式設計
- Python多執行緒程式設計(二)Python執行緒程式設計
- iOS多執行緒程式設計入門iOS執行緒程式設計