By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,272 Members | 1,358 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,272 IT Pros & Developers. It's quick & easy.

Interlocked.Increment bug?

P: n/a
Hi,

Is there any known bug related to
Interlocked.Increment(ref var)?

My client report var's value going up and down in the client/server
multile-thread application. There are about 80 clients connect to one server
though TCP client.

But actully I never decrease var.

I change its type to volatile int and use lock to increase its value

lock(this.currentCountLock)
{
this.currentCount ++;
}
and handle over to my client. (It never decreases in my machine)
Thanks,
Ryan

BTW, why volatile can not be used with ref?
Dec 15 '06 #1
Share this Question
Share on Google+
15 Replies


P: n/a
"Ryan Liu" <ad********@online.sh.cnwrote:
>Is there any known bug related to
Interlocked.Increment(ref var)?
My client report var's value going up and down in the client/server
multile-thread application. There are about 80 clients connect to one server
though TCP client.
You'll have to give us a bit more context. For instance, this code:

int ptr=0;

[thread1]
int x = Interlocked.Increment(ref ptr);
Console.WriteLine(x);

[thread2]
int y = Interlocked.Increment(ref ptr);
Console.WriteLine(y);

can quite happily print "2,1", which looks as if it's decrementing,
even though in reality it isn't and the code is working fine.
Also, are you using the Int64 version or the Int32 version? I know
there's a recently-discovered bug in the Int64 version of
Interlocked.Add. It's conceivable that Interlocked.Increment(Int64)
might have the same bug?

--
Lucian
Dec 15 '06 #2

P: n/a

Ryan Liu wrote:
BTW, why volatile can not be used with ref?
Ryan,

Because the receiving method would not be aware of the volatile
semantics. Also, if you're always using a lock then there's no need to
mark the field as volatile.

Brian

Dec 15 '06 #3

P: n/a

"Lucian Wischik" <lu***@wischik.comwrote in message
news:u3********************************@4ax.com...
| "Ryan Liu" <ad********@online.sh.cnwrote:
| >Is there any known bug related to
| >Interlocked.Increment(ref var)?
| >My client report var's value going up and down in the client/server
| >multile-thread application. There are about 80 clients connect to one
server
| >though TCP client.
|
| You'll have to give us a bit more context. For instance, this code:
|
| int ptr=0;
|
| [thread1]
| int x = Interlocked.Increment(ref ptr);
| Console.WriteLine(x);
|
| [thread2]
| int y = Interlocked.Increment(ref ptr);
| Console.WriteLine(y);
|
| can quite happily print "2,1", which looks as if it's decrementing,
| even though in reality it isn't and the code is working fine.
|
|
| Also, are you using the Int64 version or the Int32 version? I know
| there's a recently-discovered bug in the Int64 version of
| Interlocked.Add. It's conceivable that Interlocked.Increment(Int64)
| might have the same bug?
|
| --
| Lucian

How can it decrement when you are calling two times Interlocked.Increment,
I'm I missing something here?

Willy.
Dec 15 '06 #4

P: n/a

"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:uP**************@TK2MSFTNGP02.phx.gbl...
|
| "Lucian Wischik" <lu***@wischik.comwrote in message
| news:u3********************************@4ax.com...
|| "Ryan Liu" <ad********@online.sh.cnwrote:
|| >Is there any known bug related to
|| >Interlocked.Increment(ref var)?
|| >My client report var's value going up and down in the client/server
|| >multile-thread application. There are about 80 clients connect to one
| server
|| >though TCP client.
||
|| You'll have to give us a bit more context. For instance, this code:
||
|| int ptr=0;
||
|| [thread1]
|| int x = Interlocked.Increment(ref ptr);
|| Console.WriteLine(x);
||
|| [thread2]
|| int y = Interlocked.Increment(ref ptr);
|| Console.WriteLine(y);
||
|| can quite happily print "2,1", which looks as if it's decrementing,
|| even though in reality it isn't and the code is working fine.
||
||
|| Also, are you using the Int64 version or the Int32 version? I know
|| there's a recently-discovered bug in the Int64 version of
|| Interlocked.Add. It's conceivable that Interlocked.Increment(Int64)
|| might have the same bug?
||
|| --
|| Lucian
|
| How can it decrement when you are calling two times Interlocked.Increment,
| I'm I missing something here?
|
| Willy.
|
|

Sorry forget my previous post, I misread the OP's question.

Willy.
Dec 15 '06 #5

P: n/a
No - it doesn't decrement, but it can *look* like it does, depending
on which thread runs hotter.

e.g.
* thread 1 increments and receives 1, and is then paused by the
scheduler
* thread 2 increments and receives 2
* thread 2 writes "2" to the console
* thread 1 wakes up and writes "1" to the console

it never decreases... just threading...

Of course, if you increment it enough times to overlflow int.MaxValue,
then that is different ;-p

Marc
Dec 15 '06 #6

P: n/a
I am not following that. You seem to be mixing locks and interlocked. Can
we see a better sample of what your talking about.

--
William Stacey [C# MVP]

"Ryan Liu" <ad********@online.sh.cnwrote in message
news:eh***************@TK2MSFTNGP02.phx.gbl...
| Hi,
|
| Is there any known bug related to
| Interlocked.Increment(ref var)?
|
| My client report var's value going up and down in the client/server
| multile-thread application. There are about 80 clients connect to one
server
| though TCP client.
|
| But actully I never decrease var.
|
| I change its type to volatile int and use lock to increase its value
|
| lock(this.currentCountLock)
| {
| this.currentCount ++;
| }
| and handle over to my client. (It never decreases in my machine)
|
|
| Thanks,
| Ryan
|
| BTW, why volatile can not be used with ref?
|
|
Dec 15 '06 #7

P: n/a
Thanks, Brain!

Then:

if the volatile variable is only be modified by var++ , then no need to use
lock to prevent it from not increasing value?

if variable can be modified by hardware, then volatile is still needed?

Thanks,
Ryan

"Brian Gideon" <br*********@yahoo.com????
news:11**********************@t46g2000cwa.googlegr oups.com...
>
Ryan Liu wrote:
BTW, why volatile can not be used with ref?

Ryan,

Because the receiving method would not be aware of the volatile
semantics. Also, if you're always using a lock then there's no need to
mark the field as volatile.

Brian

Dec 16 '06 #8

P: n/a
Hi William,

Yes, I thought Interlocked does implicit lock or it doesn't really useful,
especially the variable is only simply advance itself.

I have abstract code following. I have a brife explain here first.

It is a client/Server application. There are 3 roles runs on differant
machines: Worker, Manager, and ApplicationServer.

Each worker works on a Item at a time.
When worker done a Item, it notifies server, and server advances the
project's current count if it is a "success" Item.

Each worker owns a thread in ApplicationServer, AppServer
talks(listen/write) to worker though that thread.

ApplicatonServer also have another backend thread run on an interval base to
read projects current value and update Managers. It check an arraylist to
see what projects need update. The project id is added to this arraylist
when worker's thread change current count in appServer.

Actual application is much more complicated then this. The following is
original code, and I am changing code to the one in comments.

public class Project
{

....

//later add this: private readonly object currentCountLock = new object();
private int currentCount; //later add volatile
public int CurrentCount
{
get
{
return this.currentCount;
}

}

/// <summary>
/// advance current by 1, in a atomic mode
/// </summary>
private void AdvanceCurrentCount()
{

Interlocked.Increment(ref this.currentCount);
//lock(this.currentCountLock)
//{
//this.currentCount ++;
//}

this.CheckIfFullAndMarkPPIfSo();
}

//80 workers' thread call this when it receive notificaton from workers
public bool DoneAnItem( ...)
{
...
if(successEnd)
{
AdvanceCurrentCount();
}
server.InfoClientQuotaChange(this);
}
}
public class Server
{

private ArrayList statusChangedProjects= new ArrayList();

// register status changed project id in the ArrayList
// then there is another thread scan this ArrayList
// to find out which project status
internal void InfoClientQuotaChange(Project project)
{
lock(this.statusChangedProjects.SyncRoot)
{
this.statusChangedProjects.Add(project.projectId);
}
}
.........
//backend thread
while(true)
{
foreach(Project p in statusChangedProjects)
{

sb.Append(p.CurrentCount);

}

//send sb.ToString() to manager

Thead.Sleep(500);

}
}

Thanks,
Ryan
"William Stacey [C# MVP]" <wi************@gmail.com写入邮件
news:OK**************@TK2MSFTNGP06.phx.gbl...
I am not following that. You seem to be mixing locks and interlocked.
Can
we see a better sample of what your talking about.

--
William Stacey [C# MVP]

"Ryan Liu" <ad********@online.sh.cnwrote in message
news:eh***************@TK2MSFTNGP02.phx.gbl...
| Hi,
|
| Is there any known bug related to
| Interlocked.Increment(ref var)?
|
| My client report var's value going up and down in the client/server
| multile-thread application. There are about 80 clients connect to one
server
| though TCP client.
|
| But actully I never decrease var.
|
| I change its type to volatile int and use lock to increase its value
|
| lock(this.currentCountLock)
| {
| this.currentCount ++;
| }
| and handle over to my client. (It never decreases in my machine)
|
|
| Thanks,
| Ryan
|
| BTW, why volatile can not be used with ref?
|
|


Dec 16 '06 #9

P: n/a
Thanks, everyone. I guess you guys are rignt, " looks as if it's
decrementing" is what happening.

I thought Interlocked does implicit lock or it doesn't really useful,
especially the variable is only simply advance itself.
And, Lucian, I am using Int32 version.

Ryan

"Marc Gravell" <ma**********@gmail.com写入邮件
news:%2****************@TK2MSFTNGP06.phx.gbl...
No - it doesn't decrement, but it can *look* like it does, depending
on which thread runs hotter.

e.g.
* thread 1 increments and receives 1, and is then paused by the
scheduler
* thread 2 increments and receives 2
* thread 2 writes "2" to the console
* thread 1 wakes up and writes "1" to the console

it never decreases... just threading...

Of course, if you increment it enough times to overlflow int.MaxValue,
then that is different ;-p

Marc



Dec 16 '06 #10

P: n/a
Oh, on the second thought, I think that is not the case.

As said in another email in this conversation thread,
I have many threads advance the var,
and another single thread read it and show to the end user.

Then this "read" thead should never "looks as if it is decrementing" ...
"Ryan Liu" <ad********@online.sh.cn写入邮件
news:Ob*************@TK2MSFTNGP02.phx.gbl...
Thanks, everyone. I guess you guys are rignt, " looks as if it's
decrementing" is what happening.

I thought Interlocked does implicit lock or it doesn't really useful,
especially the variable is only simply advance itself.
And, Lucian, I am using Int32 version.

Ryan

"Marc Gravell" <ma**********@gmail.com写入邮件
news:%2****************@TK2MSFTNGP06.phx.gbl...
No - it doesn't decrement, but it can *look* like it does, depending
on which thread runs hotter.

e.g.
* thread 1 increments and receives 1, and is then paused by the
scheduler
* thread 2 increments and receives 2
* thread 2 writes "2" to the console
* thread 1 wakes up and writes "1" to the console

it never decreases... just threading...

Of course, if you increment it enough times to overlflow int.MaxValue,
then that is different ;-p

Marc



Dec 16 '06 #11

P: n/a

Ryan Liu wrote:
Thanks, Brain!

Then:

if the volatile variable is only be modified by var++ , then no need to use
lock to prevent it from not increasing value?
You still need to aquire a lock or use an interlocked operation. The
volatile keyword does not make any guarentees about atomicity. It has
more to do with when reads and writes of the variable occur.
>
if variable can be modified by hardware, then volatile is still needed?
Not necessarily. Any mechanism that produces a memory barrier should
be sufficient. Read the following article for more details.

http://www.yoda.arachsys.com/csharp/...latility.shtml

Brian

Dec 16 '06 #12

P: n/a
Ryan Liu <ad********@online.sh.cnwrote:
Then:

if the volatile variable is only be modified by var++ , then no need to use
lock to prevent it from not increasing value?
No - you still need a lock. Think of var++ as

var = var + 1;

Another thread could change the value of var between "var + 1" being
evaluated and "var" being assigned.
if variable can be modified by hardware, then volatile is still needed?
I'm not even sure if this is possible within managed code. Could you
give an example?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 16 '06 #13

P: n/a
Ryan Liu <ad********@online.sh.cnwrote:
Yes, I thought Interlocked does implicit lock or it doesn't really useful,
especially the variable is only simply advance itself.
No - there's no lock involved. The point of Interlocked is to avoid
using a lock at all.
I have abstract code following. I have a brife explain here first.
<snip>

Unfortunately, abstract code is rarely detailed enough: with threading,
the devil is in the detail.

Personally, I'd ignore Interlocked and volatile as mechanisms and use
locks until you have evidence that the use of locks is a significant
performance hit. Getting it right with locks is non-trivial, but it's a
lot easier (IMO) than getting it right without locks.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 16 '06 #14

P: n/a

"Jon Skeet [C# MVP]" <sk***@pobox.com????
news:MP************************@msnews.microsoft.c om...
Ryan Liu <ad********@online.sh.cnwrote:
Then:

if the volatile variable is only be modified by var++ , then no need to
use
lock to prevent it from not increasing value?

No - you still need a lock. Think of var++ as

var = var + 1;

Another thread could change the value of var between "var + 1" being
evaluated and "var" being assigned.
if variable can be modified by hardware, then volatile is still needed?

I'm not even sure if this is possible within managed code. Could you
give an example?

Just a general question, I think you are right, it is impossible for
managed code.

Thanks!
--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Dec 16 '06 #15

P: n/a
Ryan Liu <ad********@online.sh.cnwrote:

<snip>
Just a general question, I think you are right, it is impossible for
managed code.
"Volatile" means different things in different memory models. It has a
well-defined meaning in C#/.NET, but that's not the same as in C, for
instance.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 16 '06 #16

This discussion thread is closed

Replies have been disabled for this discussion.