题目:
我们提供了一个类:
public class Foo {
public void one() { print("one"); }
public void two() { print("two"); }
public void three() { print("three"); }
}
三个不同的线程将会共用一个 Foo 实例。线程 A 将会调用 one() 方法
线程 B 将会调用 two() 方法
线程 C 将会调用 three() 方法
请设计修改程序,以确保 two() 方法在 one() 方法之后被执行,three() 方法在 two() 方法之后被执行。
1. 利用Mutex实现:
mutex一般用于为一段代码加锁,以保证这段代码的原子性(atomic)操作,即:要么不执行这段代码,要么将这段代码全部执行完毕。mutex主要用于互斥情况,适用于同步。
#include<mutex>
class Foo {
public:
Foo() {
m1.lock();m2.lock();
}
void first(function<void()> printFirst) {
// printFirst() outputs "first". Do not change or remove this line.
printFirst();
m1.unlock();
}
void second(function<void()> printSecond) {
// printSecond() outputs "second". Do not change or remove this line.
m1.lock();
printSecond();
m1.unlock();
m2.unlock();
}
void third(function<void()> printThird) {
// printThird() outputs "third". Do not change or remove this line.
m2.lock();
printThird();
m2.unlock();
}
private:
std::mutex m1,m2;
};
2. 使用信号量semaphore实现
semaphore可以实现资源的限额使用,既可以用于同步的互斥,也可以用于并行多任务。
信号量本质上是一个计数器(不设置全局变量是因为进程间是相互独立的,而这不一定能看到,看到也不能保证++引用计数为原子操作),用于多进程对共享数据对象的读取,它和管道有所不同,它不以传送数据为主要目的,它主要是用来保护共享资源(信号量也属于临界资源),使得资源在一个时刻只有一个进程独享。
信号量工作原理:
由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的:
(1)P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行
(2)V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1.
二元信号量:与mutex等效
二元信号量(Binary Semaphore)是最简单的一种锁(互斥锁),它只用两种状态:占用与非占用。所以它的引用计数为1。
首先看下错误代码:
#include<semaphore.h>
class Foo {
public:
Foo() {
sem_init(&mutex_,0,1);
sem_init(&m,0,1);
//sem_wait(&mutex_);
//sem_wait(&m);
}
void first(function<void()> printFirst) {
// printFirst() outputs "first". Do not change or remove this line.
sem_wait(&m);
sem_wait(&mutex_);
printFirst();
sem_post(&mutex_);
sem_post(&m);
}
void second(function<void()> printSecond) {
// printSecond() outputs "second". Do not change or remove this line.
sem_wait(&m);
sem_wait(&mutex_);
printSecond();
sem_post(&mutex_);
sem_post(&m);
}
void third(function<void()> printThird) {
// printThird() outputs "third". Do not change or remove this line.
sem_wait(&m);
sem_wait(&mutex_);
printThird();
sem_post(&mutex_);
sem_post(&m);
}
private:
sem_t mutex_,m;
};
错误原因是:三个线程/进程同步请求信号量资源m,谁在前面谁先得到,若打乱顺序,得到的线程启动也会随之打乱,如【1,3,2】则会一次执行方法1,3,2,与题意的1,2,3固定次序不符。需要在三个线程请求前,设置PV操作。
正确代码如下:
#include<semaphore.h>
class Foo {
public:
Foo() {
sem_init(&mutex_,0,1);
sem_init(&m,0,1);
sem_wait(&mutex_); ////设置wait-P操作, 互斥
sem_wait(&m); // 设置wait-P操作,资源量
}
void first(function<void()> printFirst) {
// printFirst() outputs "first". Do not change or remove this line.
// sem_wait(&m); //无需wait-P操作
// sem_wait(&mutex_); //无需wait-P操作
printFirst();
sem_post(&mutex_);
//sem_post(&m);
}
void second(function<void()> printSecond) {
// printSecond() outputs "second". Do not change or remove this line.
// sem_wait(&m);
// sem_wait(&mutex_);
sem_wait(&mutex_);
printSecond();
sem_post(&m);
}
void third(function<void()> printThird) {
// printThird() outputs "third". Do not change or remove this line.
sem_wait(&m);
printThird();
sem_post(&m);
}
private:
sem_t mutex_,m;
};
3. 使用pthread_mutex_t实现
#include<semaphore.h>
#include <pthread.h>
//pthread_mutexattr_init(pthread_mutexattr_t *mattr);
class Foo {
public:
Foo() {
pthread_mutex_init(&pmutx,NULL);
pthread_mutex_init(&pm,NULL);
pthread_mutex_lock(&pmutx);
pthread_mutex_lock(&pm);
}
void first(function<void()> printFirst) {
// printFirst() outputs "first". Do not change or remove this line.
// sem_wait(&m); //无需wait-P操作
// sem_wait(&mutex_); //无需wait-P操作
printFirst();
pthread_mutex_unlock(&pmutx);
}
void second(function<void()> printSecond) {
// printSecond() outputs "second". Do not change or remove this line.
// sem_wait(&m);
// sem_wait(&mutex_);
pthread_mutex_lock(&pmutx);
printSecond();
pthread_mutex_unlock(&pm);
}
void third(function<void()> printThird) {
// printThird() outputs "third". Do not change or remove this line.
pthread_mutex_lock(&pm);
printThird();
pthread_mutex_unlock(&pmutx);
}
private:
pthread_mutex_t pmutx,pm;
};
495



被折叠的 条评论
为什么被折叠?



