Solved

Concurrency issues — Global Variables

Posted on 2011-03-22
9
405 Views
Last Modified: 2012-05-11
Hi

Can some one explain with example and what is the solution to resolve this issue.


Regards
Karan
0
Comment
Question by:KaranGupta
  • 3
  • 3
  • 2
  • +1
9 Comments
 
LVL 4

Expert Comment

by:m_walker
ID: 35196036
Im not a c# coder, so I will leave the example (and points) to someone that is.
Are you talking about a multi treaded application accessing the same variable at the some time?

If so, I expect you will need to use a mutex to gain access to that variable.
As an approach....

wait for mutex "_mutex_var_1"
update variable
release mutex "_mutex_cat_1"

0
 

Expert Comment

by:gkuhrd2001
ID: 35196040
Hi Karan,

Can you please explain what is the problem you are facing with global variables?

Regards
Ankit
0
 

Expert Comment

by:gkuhrd2001
ID: 35196046
Hi,

As I understood by your question you can use
lock
{
}
On these variables when you are accessing them in multithreaded environment.
0
 

Author Comment

by:KaranGupta
ID: 35196253
Hi

I was reading an article why using global variable is a bad practice. This is one reason they stated as "Concurrency issues " in global variables. This is what I want to understand and what is the possible solution for this.


Regards
Karan Gupta
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 4

Expert Comment

by:m_walker
ID: 35197081
Sorry for the long post.  It will be as clear as mud so read and think and re-read.  Then ask questions.
Any code sample is only meant as an example and not actual code.  this post is about concepts.

Hope it helps in some way...

In a single theaded application, then you should not have concurrency issue, but you may use the same variable for two different things and end up with a little mess.

Consider this.
You have a global variable called Total1

Then in one function you set it up such that Total1 = 0
Then every time a "process_data" function gets called it sets Total1 += record_value;
So far so good.  Total1 is a global variable that has a running total of all records processed.
Now you call a sub_total procedure, in which you set Total1 = 0; while (some loop)  Total1+= LoopValue;
At which point Total1 now has a non-intended value.
In the sub_total procedure you call "process_data" and now Total1 is neither the Grand Total nor the SubTotal, a real mess.

As such the subtotal should be a local vairable so it cant be modified outside its function.

In a multi threaded application the mess can get bigger due to the same functions being called by different threads.  if the variables are local, then this will be thread safe, if not then the values will exists in every thread thus be changed by each thread.

If you need to have a global value in a multi threaded application (and there are some good reasons), you need to take care to ensure
1. The value is only used for the intended purpose.  This is done by you program design.
2. The value is not written two by two treads at the same time (this can result if application errors at worse, or invalid data at best).  This can be fixed by locking the variable as shown. by gkuhrd2001.

Think about this for a mulit threaded application.
You have an array for log lines.  You have a next_free pointer to the next free log entry, and a first_log entry to point to the first unprocessed log entry.
TSomeClass *LogLines[1000]; // 1000 Pointers to log data objects
int Next_Free = 0;
int First_Log = 0;

you now have a function called log data that can be called to add lines to the log list

void LogData (AnsiString LogData)
{
  LogLines[Next_Free] = new TSomeClass ();
  LogLines[Next_Free]->Time  = LogData.Time;
 LogLines[Next_Free]->LogData = LogData.LogData;
 Next_Free++;
}

Now two threads call LogData at the same time.
The first thread Creates a new object and stores it in Location 0 (next_free = 0)
The 2nd thread then runs for a while, creates a new (2nd) object and stores its point in location 0;
Then Next_Free++ in thread 2 (Next_Free = 1)
Then Next_Free++ in thread 1 (Next_Free = 2);

So we now have a valid object in location 0.  Its data will be how knows what. then we have an invalid pointer in Location 1 (as no valid object pointer was stored there)

So when the log_to_file function runs it will log some weird data from location 0 and delete that object to free up the memory.  Then application error on the invalid pointer in location 1.....  And the first object created is still taking up memory and you app cant use it.

As such a better code would be...

void LogData (AnsiString LogData)
{
 int LogPos;
   Some code to stop access to NextFree/or wait till NextFree is not locked.
   LogPos = Next_Free;
   Next_Free++;
  release lock on next_free;

  LogLines[LogPos] = new TSomeClass ();
  LogLines[LogPos]->Time  = LogData.Time;
 LogLines[LogPos]->LogData = LogData.LogData;
 
}
0
 

Author Comment

by:KaranGupta
ID: 35197772
Hi m_walker

Thanks for working so hard on this post. I really appreciate that. But I need one favour from you. In the single threaded application you have taken one example in which you are setting the value of Total1 which is a global variable. If possible please give me some more logical example so that I can understand.

In the example given above I am not sure why should we set the value of Total1 in sub_total procedure.

Thanks in advance.

Regards
Karan Gupta
0
 
LVL 4

Accepted Solution

by:
m_walker earned 250 total points
ID: 35197916
My point was just that, there is no need, but bad programming allowed it to be a problem.  When I look at my code I can see habits.
eg:

void SomeFunction1 (void)
{
int loop;
   for (loop = 0; loop < 10; loop++)
     some loop code....
}

void SomeFunction2 (void)
{
int loop;
   for (loop = 0; loop < 10; loop++)
     some loop code....
}

Note how I used the local variable "loop" in both for the loop.  local = no issue.
now consider...

int Counter;
void main (void)
{
  Conter = 0;
}

void Function2 (void)
{
   while (counter < 10)
   {
      some code...
   }
}

void Function1 (void)
{
   while (counter < 10)
   {
      some code
     function2 ();
     counter++;
   }
}

since functino2 is called from functiion1 and counter is global, and function 2 leaves count at 10, then the while loop in function 1 will only run once....

Make counter local in each function and set its initial value to 0 and the problem is fixed.

0
 
LVL 8

Assisted Solution

by:Volox
Volox earned 250 total points
ID: 35203008
The other point that I don't believe m_walker touched upon has to do with initialization....

Let's say you have something like the following:

class MyClass
{
   static List<string> globalList;

   public List<string> GetList()
   {
       if (null == globalList)
       {
          globalList = new List<string>();
          globalList.Add("first value");
       }
       return globalList;
   }
}

In the example below if two threads call GetList at the same time and they both hit the if statement at essentially the same time, they will both create a new list and assign it to the varaible and add a new value to the globalList.  Now if one thread gets through adding it's value before the other does the assignment of the new List, then the list will have one item but will be the list created by the second thread.  If both threads complete the assignment of the new list before either thread adds the first value, then you will end up with two values of "first value" in the list.  The other potential is that one thread creates the list, adds the value, and returns the list all before the assignment happens within the second thread.  In this case the caller to GetList from the first thread now has ahold of a different object entirely than the caller to GetList in the second thread.

For more examples, solutions, etc.  See discussions about threadsafe singletons.  Most common links:
http://www.yoda.arachsys.com/csharp/singleton.html
http://msdn.microsoft.com/en-us/library/ff650316.aspx
0
 

Author Closing Comment

by:KaranGupta
ID: 35204687
Thanks
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now