Thread Variable race condition

Hi,

I am not enough efficient in Threads.
Here is the problem.

i = 1
while(i < 100)

t = Thread.new do
echo(i)
end
t.join if (i % 5 == 0)
i = i + 1
end

def echo(num)
puts num
end

I get output sometimes as,

1
2
3
5
5 ==> 5 is getting duplicated whereas 4 is dropped. I feel its race
condition for variable.
6… and so on.

This error occurred for any random number.

Sometime i get the correct output.

Can anybody suggest what will be solution to avoid any such problem.
Will replacement of Thread with Process will solve problem?
I am hoping solution in Threads only if its possible.

Thanks in Advance.

On Thu, Jan 13, 2011 at 11:59 AM, Karan R. [email protected]
wrote:

t = Thread.new do
I get output sometimes as,

1
2
3
5
5 ==> 5 is getting duplicated whereas 4 is dropped. I feel its race
condition for variable.

No, this is not an indicator of a race condition. Even with proper
synchronization it may happen that two threads that you started get
scheduled before the next increment occurs and they thus print the
same value.

6… and so on.

This error occurred for any random number.

It’s not an error - although your code is of course not thread safe
because you do not synchronize.

Sometime i get the correct output.

What you consider a “correct output” (I assume a sequence where each
printed value is one higher than the previous value) is no more
correct than what you see. You may even see output where the order is
reversed (e.g. 1 2 4 3 5) because any thread might be interrupted at
any point between fetching the value and printing it. Granted, it’s
not too likely but perfectly valid and must be expected.

Can anybody suggest what will be solution to avoid any such problem.
Will replacement of Thread with Process will solve problem?

Certainly not. With processes you don’t have shared memory any more.
You would put in more effort and make processes communicate with each
other (e.g. via DRb) - typically one process will hold the counter and
others would do the printing. But even then you need proper
synchronization.

I am hoping solution in Threads only if its possible.

The question is: for which problem do you need a solution? If you
just want to print a sequence of values you don’t need threads. You
can just do

100.times {|i| puts i}

Kind regards

robert

Hi Karan,

Your problem seems to be that you are sharing state between all
the threads you are creating.

When you create a thread, all variables that are in scope at the point
it is created are accessible to the thread.

So the variable ‘i’ is visible to all the threads you create (which is
why
you can print) but it is visible to all the threads you create (which
is why you can print duplicates).

As Robert says, there’s no guarantee about scheduling. So at the point
you increment ‘i’ you could have up to 4 threads which have not yet
printed. (It can’t be five because you’re blocking the thread that makes
threads every fifth thread). In practice you’re only seeing 2 at a time
but it could be 3 or 4. Three or four are just really unlikely.

Then when you increment ‘i’ they all might print but because they all
access the same variable ‘i’ (it is in scope to them) they all print the
same thing.

I think you want to pass in ‘i’ as a variable to the thread. This will
create a thread local variable that will not increment when you
increment ‘i’ and so every thread will print the value of ‘i’ at the
point the thread was created.

i = 1
while(i < 100)

t = Thread.new(i) do |i_copy|
echo(i_copy)
end
t.join if (i % 5 == 0)
i = i + 1
end

Is this the problem you were looking to solve?

Thanks,
Scott