Does my thread need volatile variables?

Posted on 2004-08-13
Last Modified: 2011-09-20
I have a program that collects packets and stores info in a binary search tree. Every 5 minutes, I want to dump the tree to file and then repopulate with new packets. So, after I dump, I clear out the BST. My application uses libpthread. My BST is in global space, so that both threads can see it (one thread to collect, and one to dump to file).  When I don't clean up the tree, and just let it keep accumulating, the tree is fine, but when I delete and then start adding anew, the tree gets duplicates in it quite often. The function that clears the tree seems to work just fine. Could gcc 3.3.3 be pulling my leg with its optimzers and should I make my BST volatile?

This is my first program using threads and I'm not very good at debugging with threads at all.

going nuts,
Question by:dignified
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
LVL 23

Accepted Solution

Mysidia earned 168 total points
ID: 11798768
If the value of some local variable is to be modified by something external like that concurrently executing process, then yes,
that should be marked volatile

You also may need to enforce mutual exclusion when you are modifying the tree
(i.e. only one thread is modifying the tree at any given time, and no other thread
is trying to read the tree while a different one is removing from it or reading from it)

I don't know how you have it arranged, but it could be that for example, when one thread is trying
to empty the tree, another thread collects a new element and re-write parts of it, undoing some of the
remover thread's work


Author Comment

ID: 11799134
I am using mutexes also. I lock the tree before doing any operation on it, and still the odd behavior. Right now my variables are defined in global space, outside any functions. All references in functions are via pointers.

Author Comment

ID: 11802671
seems I found the bug, it was in my delete. A long story with something odd happening in my implementation. Thankfully, as far as I can tell right now, it does not involve a race condition. What is the best way to debug realtime threads anyways?
LVL 22

Assisted Solution

NovaDenizen earned 166 total points
ID: 11810333
No joke, use many printfs.  It's pretty much impossible to reliably reproduce the timing that causes intermittent bugs in multithreaded programs, especially within a debugger.  Even using printfs can change the timing so that bugs stop happening (look up the "Heisenbug principle").  Closely follow a log and your understanding of your code will improve, which should help you sleuth out what is going wrong.

When writing multithreaded programs it's important to get your multithreaded basics right the first time and have a solid design that is both timing-proof and adequate for your needs.  

Assisted Solution

aleric earned 166 total points
ID: 12032136
No, volatile has to do with optimizations.

Suppose you have this code:

int* x = f();

int k = *x;
m = 3;
m += *x;

Then the compiler knows that no memory content was
changed by the 'm = 3' line (or whatever code is there),
and therefore that it is impossible that the value of *x
has changed: both 'x' as well and ANY memory did
not change.  It is therefore allowed to optimize this
code by storing the value of *x in a temporary (or
just reusing k):

int k = *x;
m = 3;
m += k;

Volatile now has the following meaning.  If you declare

int volatile* x = f();

Then the compiler is not allowed anymore to assume
that that value remains unchanged - even if it normally
would assume this because the code that it is generating
itself doesn't change the value.

If you use threads, and do not use locking, then it is true
that the value of *x could be changed by another thread.
But that is not what volatile is intended for.  You should
instead use proper locking.  For example:

lock_for_x();   // pseudo code
int k = *x;
m = 3;
m += *x;
unlock_for_x();  // pseudo code

If the other threads also use the same lock before
accessing whatever 'x' might point to (ie, some array
of ints with a fixed size) - then you garanteed that
indeed *x wasn't changed by another thread; and
the normal optimization is allowed: no volatile

Featured Post

Containers & Docker to Create a Powerful Team

Containers are an incredibly powerful technology that can provide you and/or your engineering team with huge productivity gains. Using containers, you can deploy, back up, replicate, and move apps and their dependencies quickly and easily.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The purpose of this article is to fix the unknown display problem in Linux Mint operating system. After installing the OS if you see Display monitor is not recognized then we can install "MESA" utilities to fix this problem or we can install additio…
The purpose of this article is to demonstrate how we can upgrade Python from version 2.7.6 to Python 2.7.10 on the Linux Mint operating system. I am using an Oracle Virtual Box where I have installed Linux Mint operating system version 17.2. Once yo…
There are cases when e.g. an IT administrator wants to have full access and view into selected mailboxes on Exchange server, directly from his own email account in Outlook or Outlook Web Access. This proves useful when for example administrator want…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …

632 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