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