给你一个类:
public class Foo { public void first() { print("first"); } public void second() { print("second"); } public void third() { print("third"); } }
三个不同的线程 A、B、C 将会共用一个 Foo 实例。
线程 A 将会调用 first() 方法
线程 B 将会调用 second() 方法
线程 C 将会调用 third() 方法
请设计修改程序,以确保 second() 方法在 first() 方法之后被执行,third() 方法在 second() 方法之后被执行。
提示:
尽管输入中的数字似乎暗示了顺序,但是我们并不保证线程在操作系统中的调度顺序。
你看到的输入格式主要是为了确保测试的全面性。
方法一:信号量while?
typedef struct { // User defined data may be declared here. int mutex_1; // int mutex_2; } Foo; Foo* fooCreate() { Foo* obj = (Foo*) malloc(sizeof(Foo)); // Initialize user defined data here. obj->mutex_1 = 1; // obj->mutex_2 = 1;//初始化 return obj; } void first(Foo* obj) { // printFirst() outputs "first". Do not change or remove this line. while(obj->mutex_1!=1); printFirst(); obj->mutex_1 = 2; } void second(Foo* obj) { // printSecond() outputs "second". Do not change or remove this line. while(obj->mutex_1!=2); printSecond(); obj->mutex_1 = 3; } void third(Foo* obj) { while(obj->mutex_1!=3); // printThird() outputs "third". Do not change or remove this line. printThird(); } void fooFree(Foo* obj) { // User defined data may be cleaned up here. free(obj); }
方法二:信号量
#include<semaphore.h>
信号量的数据类型为结构sem_t,它本质上是一个长整型的数。
函数sem_init()用来初始化一个信号量。它的原型为:int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。信号量用sem_init函数创建的,下面是它的说明:
int sem_init (sem_t *sem, int pshared, unsigned int value); 这个函数的作用是对由sem指定的信号量进行初始化,设置好它的共享选项,并指定一个整数类型的初始值。pshared参数控制着信号量的类型。如果 pshared的值是0,就表示它是当前里程的局部信号量;否则,其它进程就能够共享这个信号量。我们现在只对不让进程共享的信号量感兴趣。 (这个参数 受版本影响), pshared传递一个非零将会使函数调用失败,属于无名信号量。
函数sem_post( sem_t *sem )用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。int sem_post(sem_t *sem);sem_post() 成功时返回 0;错误时,信号量的值没有更改,-1 被返回,并设置errno 来指明错误。错误 EINVAL sem 不是一个有效的信号量。 EOVERFLOW 信号量允许的最大值将要被超过。
函数sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。
函数sem_destroy(sem_t *sem)用来释放信号量sem,属于无名信号量。
typedef struct { // User defined data may be declared here. sem_t one; sem_t two; } Foo; Foo* fooCreate() { Foo* obj = (Foo*) malloc(sizeof(Foo)); sem_init(&(obj->one), 0, 0); sem_init(&(obj->two), 0, 0); // Initialize user defined data here. return obj; } void first(Foo* obj) { // printFirst() outputs "first". Do not change or remove this line. printFirst(); sem_post(&(obj->one)); } void second(Foo* obj) { // printSecond() outputs "second". Do not change or remove this line. sem_wait(&(obj->one)); printSecond(); sem_post(&(obj->two)); } void third(Foo* obj) { sem_wait(&(obj->two)); // printThird() outputs "third". Do not change or remove this line. printThird(); } void fooFree(Foo* obj) { // User defined data may be cleaned up here. sem_destroy(&(obj->one)); sem_destroy(&(obj->two)); }
方法三:线程
typedef struct { pthread_mutex_t mutex_1; pthread_mutex_t mutex_2; //创建互斥锁 } Foo; Foo* fooCreate() { Foo* obj = (Foo*) malloc(sizeof(Foo)); pthread_mutex_init(&obj->mutex_1, NULL); pthread_mutex_init(&obj->mutex_2, NULL); pthread_mutex_lock(&obj->mutex_1); pthread_mutex_lock(&obj->mutex_2); return obj; } void first(Foo* obj) { printFirst(); pthread_mutex_unlock(&obj->mutex_1); } void second(Foo* obj) { pthread_mutex_lock(&obj->mutex_1); //阻塞调用 获取锁 printSecond(); pthread_mutex_unlock(&obj->mutex_1); pthread_mutex_unlock(&obj->mutex_2); } void third(Foo* obj) { pthread_mutex_lock(&obj->mutex_2); printThird(); pthread_mutex_unlock(&obj->mutex_2); //释放互斥锁 } void fooFree(Foo* obj) { pthread_mutex_destroy(&obj->mutex_1); pthread_mutex_destroy(&obj->mutex_2); //销毁互斥锁 free(obj); }