Thread.MemoryBarrier()

  • Thread starter Thread starter Peter Morris
  • Start date Start date
P

Peter Morris

Is this test case accurate?

bool someResult = false;
var thread = new Thread( () => someResult = true );
thread.Start();
thread.Join();

thread.MemoryBarrier();

Assert.IsTrue(someResult);


I ask because I don't want to make someResult a member of my class just so
that I can make it volatile (it's a test case, I don't want to pollute the
class with members that are used for a single test method).


Thanks

Pete
 
Is this test case accurate?

bool someResult = false;
var thread = new Thread( () => someResult = true );
thread.Start();
thread.Join();

thread.MemoryBarrier();

Assert.IsTrue(someResult);

I ask because I don't want to make someResult a member of my class just so
that I can make it volatile (it's a test case, I don't want to pollute the
class with members that are used for a single test method).

Why not just Thread.VolatileRead & VolatileWrite?
 
Peter said:
Is this test case accurate?

bool someResult = false;
var thread = new Thread( () => someResult = true );
thread.Start();
thread.Join();

thread.MemoryBarrier();

Assert.IsTrue(someResult);


I ask because I don't want to make someResult a member of my class
just so that I can make it volatile (it's a test case, I don't want
to pollute the class with members that are used for a single test
method).

Multithreaded code is non-deterministic. Testing isn't reliable.

You need to find a better way to assess the quality of such code than
running test suites.
 
Why not just Thread.VolatileRead & VolatileWrite?

Yes, I could do that. But still I'd like to understand MemoryBarrier
better, do you know if my example is correct?


Pete
 
Multithreaded code is non-deterministic. Testing isn't reliable.
You need to find a better way to assess the quality of such code than
running test suites.

public ......................(int id)
{
while (true)
{
01: Create an object-space session (unit of work, whatever you want
to call it)
02: Fetch data from database
03: Create objects from data
04: Modify data
05: Update database
06: Dispose of object space
break;
}
}

I needed to ensure that if two threads execute this code using the same ID
at the same time that one of them would detect another thread has modified
the data since it retrieved it from the DB, it should then handle the error
and re-try. To do this I would need to inject code between step 2 and step
5, which I obviously cannot do. So what I did was this

01: On my object space I re-registered my IPersistenceService with a class
that executes an UpdatingDatabase event before passing on the request to
OriginalPersistence.UpdateDatabase
02: I created a single ManualResetEvent which my test uses to indicate it is
time to start the race condition.
03: Created 2 ManualResetEvents. Each thread has its own, it signals the
event from the UpdatingDatabase event so that I know when both threads have
reached step 5

In the event I do this
EventToIndicateIAmReadyToUpdateTheDatabase.Set();
EventToIndicateStartOfRaceCondition.Wait();

So I know that my 2 threads have passed step 4 before either are allowed to
execute step 5, at which point my race condition executes. The test is
simple, it works 100% of the time, and it's quick too. I can't think of
another way to test this, can you?
 
Peter said:
public ......................(int id)
{
while (true)
{
01: Create an object-space session (unit of work, whatever you
want to call it)
02: Fetch data from database
03: Create objects from data
04: Modify data
05: Update database
06: Dispose of object space
break;
}
}

I needed to ensure that if two threads execute this code using the
same ID at the same time that one of them would detect another thread
has modified the data since it retrieved it from the DB, it should
then handle the error and re-try. To do this I would need to inject
code between step 2 and step 5, which I obviously cannot do. So what

It sounds like you did exactly that.
I did was this
01: On my object space I re-registered my IPersistenceService with a
class that executes an UpdatingDatabase event before passing on the
request to OriginalPersistence.UpdateDatabase
02: I created a single ManualResetEvent which my test uses to
indicate it is time to start the race condition.
03: Created 2 ManualResetEvents. Each thread has its own, it signals
the event from the UpdatingDatabase event so that I know when both
threads have reached step 5

In the event I do this
EventToIndicateIAmReadyToUpdateTheDatabase.Set();
EventToIndicateStartOfRaceCondition.Wait();

So I know that my 2 threads have passed step 4 before either are
allowed to execute step 5, at which point my race condition executes.
The test is simple, it works 100% of the time, and it's quick too. I
can't think of another way to test this, can you?

You can use a single thread. When you get to the "past step 4 but before
step 5" where you're currently making it wait, then make a change to the
database.
 
Peter said:
The test is simple, it works 100% of the time, and it's quick too. I
can't think of another way to test this, can you?

Also, the test represents a particular ordering. But your race can appear
with the conflicting change occurring between any two instructions, and your
test does not produce all possible orderings. So passing the test is no
guarantee that the race is prevented. (For example it could correctly deal
with a conflict during step 4, but not during step 3).
 
Back
Top