Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

synchronizing reads to a java collection

so i want to have an arraylist that stores a series of stock quotes. but i keep track of bid price, ask price and last price for each.

of course at any time, the bid ask or last of a given stock can change.

i have one thread that updates the prices and one that reads them.

i want to make sure that when reading no other thread is updating a price. so i looked at synchronized collection. but that seems to only prevent reading while another thread is adding or deleting an entry to the arraylist.

so now i'm onto the wrapper approach:

public class Qte_List {
private final ArrayList<Qte> the_list;

public void UpdateBid(String p_sym, double p_bid){
    synchronized (the_list){
        Qte q = Qte.FindBySym(the_list, p_sym);
        q.bid=p_bid;}
}

public double ReadBid(String p_sym){
    synchronized (the_list){
        Qte q = Qte.FindBySym(the_list, p_sym);
        return q.bid;}
}

so what i want to accomplish with this is only one thread can be doing anything - reading or updating an the_list's contents - at one time. am i approach this right?

thanks.

like image 733
jeff Avatar asked May 19 '10 06:05

jeff


3 Answers

Yes, you are on the right track and that should work.

But why not use the existing Hashtable collection, which is synchronized, and provides a key-value lookup already?

like image 56
Timothy Avatar answered Nov 02 '22 12:11

Timothy


As I understand it you are using the map to store the quotes; the number of quotes never changes, but each quote can be read or modified to reflect current prices. It is important to know that locking the collection only protects against changes to which Quote objects are in the map: it does not in any way restrict the modification of the contents of those Quotes. If you want to restrict that access you will have to provide locking on the Quote object.

Looking at your code however I don't believe you have a significant synchronization problem. If you try to do a read at the same time as a write, you will either get the price before or the price after the write. If you didn't know the write was going to occur that shouldn't matter to you. You may need locking at a higher level so that

if (getBidPrice(mystock)<10.0) {
  sell(10000);
}

happens as an atomic operation and you don't end up selling at 5.0 rather than 10.0.

If the number of quotes really doesn't change then I would recommend allowing Qte objects to be added only in the constructor of Qte_List. This would make locking the collection irrelevant. The technical term for this is making Qte_List immutable.

like image 21
DJClayworth Avatar answered Nov 02 '22 13:11

DJClayworth


That looks like a reasonable approach. Nit-picking, though, you probably shouldn't include the return statement inside the synchronized block:

public double ReadBid(String p_sym){
    double bid;
    synchronized (the_list) {
        Qte q = Qte.FindBySym(the_list, p_sym);
        bid = q.bid;
    }

    return bid;
}

I'm not sure if it's just my taste or there's some concurrency gotcha involved, but at the very least it looks cleaner to me ;-).

like image 1
Santa Avatar answered Nov 02 '22 14:11

Santa