C++多线程笔试编程题

子线程循环 10 次,接着主线程循环 100 次,接着又回到子线程循环 10 次,接着再回到主线程又循环 100 次,如此循环50次,试写出代码。

2017.2.11日更新:
之前写这几段代码忘记对mutex和condition调用pthread_destroy()!

代码如下:

#include 
#include 
#include 
#include 

#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; testwhile(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; testwhile(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 
#include 
#include 

#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; ivoid *)(thread_id+i));
    for(int i=0; ireturn 0;
}

注意我的线程id是用单独的数组存储并传递给线程的,如果直接使用for循环中的&i,那么线程局部thread_id会随着i改变。

方法二:使用原子操作(推荐)

#include 
#include 
#include 

#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; iwhile(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; ivoid *)(thread_id+i));
    for(int i=0; ireturn 0;
}

读者写者问题
这也是一个非常经典的多线程题目,题目大意如下:有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者读时写者也不能写。

做到这道题为之,我已经不耐烦POSIX线程API了,我要拿起我的老本行C++来做了。

#include 
#include 
#include 
#include 

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& 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& 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& 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 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。它们基本功能是一样的,后者功能更丰富一些。

你可能感兴趣的:(多线程)