c# - Thread synchonization -


i have list of commands processed concurrently on multiple threads. list static, each thread generates output , not interfere other threads, works ok far.

some of commands require complex calculations on dataset accompanies command. result of calculations same threads. @ moment each thread performs calculations when reaches command waste of time , resources.

what perform calculation once , share results between threads. thread reaches first command starts calculation, other threads reach command wait till calculation complete , use result.

i have little experience thread synchronization , not know synchronization primitives should use scenario , should put lock on calculation. can tell me classes (for synchronization) should use in scenario , thread should wait , on object?

my code looks this:

private void threadfunc(object state) {     context ctx = (context)state;      command cmd = ctx.commandlist;     processor proc = ctx.processor;      while (cmd != null)     {         switch(cmd.type)         {             case commandtype.simple:                 proc.executesimplecommand(cmd);                 break;             case commandtype.complex:                 cmd.data = computedata(cmd.dataset);                 proc.executecomplexcommand(cmd);                 break;         }          cmd = cmd.next;     } } 

the computedata method performs complex calculation , result stored on command.
code has problem @ moment because each thread sets data property on same command object since calculation result same threads code works.

i thinking of i'm not sure if correct:

case commandtype.complex:     lock (cmd)     {         if (cmd.data == null)         {             cmd.data = computedata(cmd.dataset);         }     }     proc.executecomplexcommand(cmd);     break; 

edit: i'm limited on .net 2.0 @ moment.

edit 2: list fixed, elements not change. threads read list, not modify list.
i'll try example: list contains elements a, b , c , processed threads t1 , t2. when t1 reaches b, calls computedata method , stores result in property of b. when t2 reaches b waits till calculation on (assuming t1 reached b before , called computedata) , uses result. want achieve.

basically you're attempting grab head of linked list , move next location. 'grab' issue here; it's easy put loop around it.

with locks

the easy solution use lock:

private static object lockobject = new object();  // ...  command current; lock (lockobject) {     current = commandlist;     commandlist = commandlist.next; }  // use current. 

alternatively, can use spinlock.

without locks

while it's tricky make thread-safe code without locks, here's attempt (warning: there might bugs in here; haven't thoroughly checked code!):

thread.memorybarrier(); // read barrier var list = commandlist;  if (list != null) {     var next = list.next;     if (interlocked.compareexchange(ref commandlist, next, list) == list)     {        // execute code on 'list'.     }     else      {        // changed. try again.     } } 

let's change question...

sometimes dialogue makes things more confusing...

the thread reaches first command starts calculation, other threads reach command wait till calculation complete , use result.

and

simple commands can run in parallel without problems. complex commands can run in parallel (this i'm doing now) same calculation performed on each thread , waste of time.

so let's straight: let's assume have chain a->b->c , c simple commands , b complex command. want a,b run in parallel , want run c after b has finished. while executing b should wait until done.

one simple solution comes mind: let's assume simple commands have no data , complex commands have data. you've said list created before invoking all. means don't have lot of synchronization.

basically can follows:

var current =  this.commandlist;  while (current != null) {     if (current.data != null) // complex command? (b)     {         lock (current.data) // threads wait here except 1         {             if (current.executed) // execute once.             {                  // go ahead , execute it, single threaded                 // [code]                  current.executed = true;             }         }     }     else     {         bool executehere = false;          // simple command.         lock (lockobject) // shared lock object         {             executehere = !command.executed; // execute in thread?             command.executed = true;         }          // true in 1 thread only, multiple a's/c's can executed in parallel.         if (executehere)          {             // execute simple command             // [code]         }     }     current = current.next; } 

Comments

Popular posts from this blog

javascript - Laravel datatable invalid JSON response -

java - Exception in thread "main" org.springframework.context.ApplicationContextException: Unable to start embedded container; -

sql server 2008 - My Sql Code Get An Error Of Msg 245, Level 16, State 1, Line 1 Conversion failed when converting the varchar value '8:45 AM' to data type int -