C# Multithreading Synchronisation

Soldato
Joined
9 Jul 2006
Posts
3,322
Location
London
Hey guys. I wouldnt usually post asking for help with assignments on here, but I feel like im going round in circles with this one.
Basically clicking on each "Hanger" spawns an aeroplane, current represented by coloured squares, they then follow the runway round to the takeoff section. The assignment spec is very vague, but you get the idea.

I'm having problems with race conditions that appear when two planes are queueing for the same section of tarmac. They keep running out of sync and overwriting eachothers data. I'm hoping for a few tips/pointers, maybe a good way of queueing them so that one isnt left waiting indefinetly?


The VS 2005 project file, source code, and assignment spec can be found here.

Thanks in advance :)
 
Only breifly looked at assignment but I assume a section of tarmac can be queried as to whether it is empty.

If the tarmac is empty the thread will move the plane into that section. Use the lock object throughout this so that another thread cannot query the tarmac and come to the same result overwriting the other plane.

For the whole queueing issue, I would for each tarmac have a list of planes wanting to move onto it, and use a priority system, move the plane with the highest priority onto the tarmac and increase the priority of all planes that are still waiting by one.

This would also the ability of important planes to move around quicker as their priority could always be increased by a factor relevant to their importance.


Hope that makes sense ;d
 
Yeah I was thinking about making some sort of queue list, ill give it a go since I've had no other ideas, cheers mate :)
 
What you really need is a way of signalling between threads, for which wait handles can be very useful (specifically AutoResetEvent and ManualResetEvent; read up on them here).

You could just have a queue of wait handles for each section of tarmac that represent the planes waiting for it. When the plane currently on it finishes, just signal the first waiting thread by setting the first wait handle in the queue.

Of course, that's assuming you're assigning a thread to handle each plane permanently (I haven't looked very thoroughly through your code :p).
 
Last edited:
Inquisitor said:
What you really need is a way of signalling between threads, for which wait handles can be very useful (specifically AutoResetEvent and ManualResetEvent; read up on them here).

You could just have a queue of wait handles for each section of tarmac that represent the planes waiting for it. When the plane currently on it finishes, just signal the first waiting thread by setting the first wait handle in the queue.

Of course, that's assuming you're assigning a thread to handle each plane permanently (I haven't looked very thoroughly through your code :p).
No, i've got each section of tarmac as a seperate thread, and they just pass the plane details between eachother. I'll have a look at waits aswell, nice one lads :D

Just changed the background images, so now instead of buttons and a plain coloured form, i have photos of hangers and a grass field :p
 
Welshy said:
Just changed the background images, so now instead of buttons and a plain coloured form, i have photos of hangers and a grass field :p
A thoroughly important aspect of the program taken care of :P

I always do that when I'm procrastinating ;d
 
Giving up for the night now, been messing around with it for a good 6 hours now :eek:

Will post back tomorrow with yet more questions/problems :D
 
Why have you got one thread per runway?!? You should have one object per piece of runway, and one thread per plane. The plane threads should then query the runway objects.
 
Lagz said:
Why have you got one thread per runway?!? You should have one object per piece of runway, and one thread per plane. The plane threads should then query the runway objects.
That was what I was thinking :p
 
Yeah does seem an over complicated / unusual way of doing it. I had a similar assignment when I was at uni.... Boats wanting to make use of a draw bridge or something. Each boat (or in this case plane) should be on their own thread and then try and get that resource (bridge / run way) assigned to their use.
 
I did think about having one thread per plane, but I couldn't think of a good way to do it. If somebody could outline how to have each plane as a thread then it would be appreciated.

Edit: Bear in mind this is the first time I've EVER used threads :p
 
Last edited:
I too wondered why you were using threads the wrong way round, just assumed you had been told to do it that way.

I would od it as follows:

-Array of "Tarmac Section" Objects.
-Each tarmac section has a variable which holds a reference to the plane that is on the tarmac, null if none
-Each plane has a reference to the tarmac they reside on, so it can set the tarmac to object to empty once it has left it
-A list of each plane waiting to enter tarmac, using priority system I outlined earlier. The priority system will also allow you to set it so planes coming from certain tarmacs have a higher priority, for example planes sitting on the tarmac leading off the runway will require a high priority as they need to move asap for when the next incoming plane arrives.
 
This is one way (not the best!). . .

Code:
class RunwaySection
    {
        //The plane currently in the section
        private Plane mPlane = null;

        /// <summary>
        /// Locks the runway section - should be called
        /// by the plane when it wants to move into the section.
        /// 
        /// The method call will block until the plane has
        /// successfully acquired the runway
        /// </summary>
        public void lockRunway(Plane iPlane)
        {
            lock (this)
            {
                while (mPlane != null)
                {
                    //The runway section is in use
                    //by another plane, so block on
                    //this object.
                    Monitor.Wait(this);
                }
                //We have acquired the runway :-)!
                mPlane = iPlane;
            }
        }

        /// <summary>
        /// Should be called by each plane as it leaves
        /// the runway section
        /// </summary>
        public void unlockRunway()
        {
            lock (this)
            {
                //Section is no longer in use
                mPlane = null;
                //Wake up any planes that are waiting to
                //acquire the section of runway
                Monitor.PulseAll(this);
            }
        }

    }

There is almost certainly a c# class that implements almost exactly what I have just implemented above, but by going to this level you get to see a little more what is going on. It might look a bit confusing, so I will *attempt* to explain.

1. You have 1 thread per plane (presumably created by a Hanger object?)
2. When a plane wants to move into a runway section it calls lockRunway on that segment, passing itself as the argument. If the segment is not in use, it sets can enter the segment.

If the segment is in use then the thread released the lock on the object and blocks (this is what Monitor.wait does). This thread will be woken up by planes moving out of the runway segment (see 3).

3. When a plane leaves the runway segment it should call unlockRunway. This method sets the plane to null and then wakes up any planes which are blocked trying to obtain that piece of runway (this is what Monitor.PulseAll does). This creates a race condition - if more than 1 plane was blocked they will all be woken up. The first one to be executed will acquire the lock and be able to return from the lockRunway method. The others will all get blocked again - this is why you need the while loop in lockRunway.



This is a lot more low level than you probably need to go (i.e: you can probably make use of some standard library classes instead), but hopefully this gives you an insight into how threading and locking works.

You might want to also note a few things:

- It is up to you to ensure that a plane ALWAYS releases a bit of runway after it moves out of it. This can be an issue if exceotions can be thrown between acquiring and releasing a segment. The solution is normally to use finalize blocks :-)!
- This implementation is far from perfect. You might want the plane who has been waiting the longest to get priority when all waiting planes are woken up. In this implementation it is just random. You can implement ordering by adding waiting threads to a list, and then only waking up the plane at the head of the list.
 
Last edited:
Lagz said:
You can implement ordering by adding waiting threads to a list, and then only waking up the plane at the head of the list.
What are these wait threads? I've read about them, but they're used in a context that I can't adapt to this assignment. Are they like a ThreadPool? :confused:
 
Welshy said:
What are these wait threads? I've read about them, but they're used in a context that I can't adapt to this assignment. Are they like a ThreadPool? :confused:

I don't mean wait threads (whatever they are). I mean that you could have a list which you stick the threads on before you block them.
 
Ok right, I'm getting somewhere now.

I have the MainWindow class creating a new thread when you click on a hanger, which starts the "run()" method in the Plane class.

I have an Array of Sections and an ArrayList of Planes in the MainWindow class.

The planes are created and threads started no problem at all, and the planes move to the bottom of the first sections of tarmac :)

Hopefully my final question, but what would be the best way to pass the Plane to the next section? As the array of Sections is a member in the MainWindow class, the Plane threads cannot access it directly. Passing the entire array into each plane seems a bit like overkill, maybe use a delegate to collect and return the next Section? Pretty much as I had before.
 
Welshy said:
Hopefully my final question, but what would be the best way to pass the Plane to the next section? As the array of Sections is a member in the MainWindow class, the Plane threads cannot access it directly. Passing the entire array into each plane seems a bit like overkill, maybe use a delegate to collect and return the next Section? Pretty much as I had before.

I dont think its particularly important. Remember that when you "pass the entire array" you are actually only passing a reference to the array, so it isn't really overkill in a copying sense.

Ideally you should come up with the most natural OO design you can. I would probably have an airport class which holds all the segments and information about how they are linked together. I would then pass a reference to the airport to each Plane object.
 
Remember to use lock when a thread uses the airport data though as they will all be sharing the same airport object.

Also don't use ArrayList use type defined lists!!!

Think its in System.Collections.Generic

List<Plane> PlaneList = new List<Plane>();

Type safetly ***.
 
Back
Top Bottom