【问题标题】:Implementing a stock exchange using monitors使用监视器实现证券交易所
【发布时间】:2013-04-29 01:25:43
【问题描述】:

我正在尝试使用 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
    }
  }
}

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

【问题讨论】:

  • 在我看来,这段代码可能会导致死锁情况,因为您在等待后增加了available_shares变量,所以买家总是会在这种情况下失败,卖家和买家都等待永远
  • 很可能是这样。你知道我怎么能解决这个问题吗?或者您能否建议一种不同的实施方式来实施这样的证券交易所?
  • @ladypada boost lockfree 应该会有所帮助,但请注意 stackoverflow.com/questions/14893246/… 顺便说一句:请教我如何存储和处理订单。

标签: concurrency stock mutual-exclusion


【解决方案1】:

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

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

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);
  }
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-17
    • 2017-09-19
    • 1970-01-01
    相关资源
    最近更新 更多