1

我正在尝试使用 Hoare 的监视器实现证券交易所。

它有两个函数 buy() 和 sell() 如下:

buy(procid, ticker, nshares, limit)
sell(procid, ticker, nshares, limit)

并且应该打印有关买方 ID、卖方 ID、股票代码、股票数量和价格的信息。公平总是得到满足。

我的解决方案的伪代码如下,但并不完整。它基本上为每个代码使用条件变量队列。当向证券交易所发送卖单时,卖方进程在此队列中进入休眠状态,并且买方进程向该卖方进程发出信号,如果条件(匹配价格限制和股票数量)满足,它想要购买。

monitor SE {
  int available_shares;
  int price;

  sell(procid, ticker, nshares, limit) {
    wait(ticker); // put sell order in ticker queue
    available_shares += nshares;
    price = limit;
    printf("Starting transaction with seller %i", procid);
  }

  buy(procid, ticker, nshares, limit) {
    if (limit <= price && nshares <= available_shares) {
      signal(ticker);
      available_share -= nshares;
      printf("Completing transaction with buyer %i", procid);
      printf("Transacting %i %s shares at %i", nshares, ticker, limit);
    } else {
      wait(ticker); // put buy order in ticker queue
    }
  }
}

这种方法是否能够处理多个代码的多个买卖订单?还是会导致死胡同?

4

1 回答 1

2

为了解决死锁问题,我将使用两个条件变量,一个用于买家,一个用于卖家。每个方法首先修改 available_shares,然后用信号通知自己的条件变量,最后等待另一个条件变量。尽管如此,每个操作在唤醒以完成事务或再次进入睡眠后,都必须重新检查有关 available_shares 的条件。

这里的问题是,这无法跟踪您从/向谁购买/出售了多少。它甚至不保证卖方在交易中出售其所有股份。因此,在回答您最初的问题时,我看不出这种方法如何能够处理多个代码的多个买卖订单。我提出了另一种解决方案,它使用 HashTable 或字典,其中每个键是一个限制,每个值是一个优先级队列或由股票代码排序的排序列表

monitor SE {
  int available_shares;
  int price;
  Dictionary<int, SortedList<int, Transac>> Ts;

  sell(procid, ticker, nshares, limit) {
    Transac t = new Transac(procid, nshares, limit);

    Ts[limit].enqueue(ticker, t); //probably you should verify first if the entry is not null 

    available_shares += nshares;

    notifyAll(tickerB);

    while(Ts[limit][ticker] > 0)
      wait(tickerS); 

    printf("Starting transaction with seller %i", Ts[limit][ticker].procid);
  }

  buy(procid, ticker, nshares, limit) {

    int nshares_copy = nshares;

    while(true){
      int cnt = 0;
      List<Transac> tmp = new List<Transac>();
      for(int i = 0; i < Ts.keys.length && cnt < nshares; i++){
          if(Ts.keys[i] <= limit){
            for(int j = 0; j < Ts[Ts.keys[i]].lenght && cnt < nshares; j++){
                cnt += Ts[Ts.keys[i]][j].nshares;
                tmp.add(Ts[Ts.keys[i]][j]);
            }
          }
      }
      if(nshares <= cnt){
          available_share -= nshares;

          foreach(Transac t in tmp){
            int min = min(t.nshares, nshares);
            t.nshares -= min;
            nshares -= min;
          }
          break;
      } else {
          wait(tickerB);
      }
    }

    notifyAll(tickerS);

    printf("Completing transaction with buyer %i", procid);
    printf("Transacting %i %s shares at %i", nshares_copy, ticker, limit);
  }
}

我使用监视器来遵循您最初的想法,但我不得不说我认为这不是最好的方法。我认为更细粒度的锁可以为您提供更好的性能(例如锁或原子操作)。注意:代码未经测试。所以,我可能遗漏了一些实现细节

于 2013-04-30T19:28:26.017 回答