Dendei
Dendei

Reputation: 571

Lock only if value is same?

If i have an function that edits the database in my webservice that i only want one thread to execute at one time if they try to edit the same row.

void EditCheck(long checkid)
    {

        if (isCheckCosed)
            throw new Exception("check is already closed");

        //do stuff

        //after i edit my check i want to close it.
        CloseCheck();
    }

i know i can lock the whole function, but then i loose preformance because its almost never that different threads will try to edit the same check.

is there a way to only lock out other threads that have the same checkid?

UPDATE

i use OleDbConnection and MySqlConnection

OleDbCommand oleDbCommand = AccessTrans != null ?
new OleDbCommand(sql, AccessConn, AccessTrans) : new OleDbCommand(sql, AccessConn); 
oleDbCommand.ExecuteNonQuery();

the same function for MySqlCommand

and then i jus use the normal INSERT and UPDATE sql commands. the and the transaction is checked if it is present or not. so this functions works if you want an transaction or not in your upper level function.

for reading from the database i'll fill DataTable

OleDbCommand oleDbCommand = AccessTrans != null ? new OleDbCommand(sql, AccessConn, AccessTrans) : new OleDbCommand(sql, AccessConn);
OleDbDataAdapter dAdapter = new OleDbDataAdapter();
dAdapter.SelectCommand = oleDbCommand;
dAdapter.Fill(dTable);
return dTable;

Upvotes: 17

Views: 3347

Answers (2)

Martin Podval
Martin Podval

Reputation: 1117

As you want to improve performance, you should make locking at the recent moment as possible. As you use database, you can use DB locking. You got two options:

  1. Use Select for update, look at Proper way to SQL select and update
  2. Use optimistic locking which is IMHO best approach to do that, http://en.wikipedia.org/wiki/Optimistic_concurrency_control or http://docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch05.html

Note that both approaches allows you to use DB resources more than programmatic ones. This is better more that proposed dictionary, why?

Once you will duplicate data, those in DB are duplicated in the runtime dictionary, you are forced to sync them, so if someone updates database and add new id you need to immediately update dictionary.

Sure, it's doable for small maintaining (e.g. repository) class but once your project gets grow, some of your colleague can forget this information and you will start to find such kind of bugs.

Upvotes: 0

Servy
Servy

Reputation: 203812

You can use a ConcurrentDictionary to map each id to an object that you can lock on:

public class Foo
{
    private ConcurrentDictionary<long, object> dictionary = 
        new ConcurrentDictionary<long, object>();

    private void EditCheck(long checkid)
    {
        var key = dictionary.GetOrAdd(checkid, new object());
        lock (key)
        {
            //Do stuff with key
        }
    }
}

Upvotes: 31

Related Questions