MemoryBarrier vs volatile vs lock [英] MemoryBarrier vs volatile vs lock

查看:61
本文介绍了MemoryBarrier vs volatile vs lock的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,


我正试图让我的同步。


文档似乎说创建一个volatile field给出了一个

的记忆障碍。


太棒了!但是当我做一点性能测试时,Thread.MemoryBarrier比访问volatile int慢40倍。另外,我没有看到增加volatile int的时间和

非易失性int之间的显着差异。


差异是否都可以归因于函数调用的开销?


当我阅读关于Thread.VolatileWrite的文档时,它说所有其他的

处理器保证立即看到你的写。


但是当我使用反射器反编译VolatileWrite时,我得到:


public static void VolatileWrite(ref int address,int value)

{

Thread.MemoryBarrier();

address = value;

}


现在,如果MemoryBarrier在写入之前,我无法在处理器2上的处理器1读取值(通过缓存)上抛出

MemoryBarrier并且

然后写入处理器1上的地址,现在下一次读取地址

processor2得到它的缓存从新写入之前的价值。


(男孩,因为要阅读这篇文章很难写。)

processor1:Thread .MemoryBarrier

processor2:读取地址获取old_value(old_value缓存)

processor1:address = new_value

processor2:读取地址仍返回old_value。


VolatileWrite的编写方式似乎保证在写入之前任何写入它都会在写入之前到达主内存但是不保证

这个写。


谢谢

解决方案

我运行以下代码的结果:


baseline = 00:00:00.0318235

volatile_int = 00:00:00.0320384

内存障碍= 00:00:01.1449614

VolatileMethods = 00:00:02.3170651

锁定= 00:00:00.4858723

Interlocked = 00:00:00.0907154

代码:


使用系统;

使用S ystem.Collections.Generic;

使用System.Text;

使用System.Diagnostics;

使用System.Threading;


命名空间ConsoleApplication1

{

类程序

{

私有对象_syncobj = new Object();

private int m_a;

private volatile int m_v;


public void Test()

{

秒表sw =新秒表();


m_a = 0;

sw.Start() ;

for(int i = 0;我<千万; ++ i)

m_a ++;


Console.WriteLine(" baseline =" + sw.Elapsed);


sw.Reset();

m_v = 0;

sw.Start();

for(int i = 0 ; i< 10000000; ++ i)

m_v ++;


Console.WriteLine(" volatile_int =" + sw.Elapsed);


sw.Reset();

m_v = 0;

sw.Start();

for(int i = 0; i< 10000000; ++ i)

{

// Thread.MemoryBarrier();

m_v ++ ;

Thread.MemoryBarrier();

}


Console.WriteLine(" Memory Barriers =" + sw。经过);


sw.Reset();

m_a = 0;

sw.Start();

for(int i = 0; i< 10000000; ++ i)

Thread.VolatileWrite(ref m_a,Thread.VolatileRead(ref m_a)+1);


Console.WriteLine(" VolatileMethods =" + sw.Elapsed);


sw.Reset();

m_a = 0;

sw.Start ();


for(int i = 0;我<千万; ++ i)

{

lock(_syncobj)

{

m_a ++;

}

}


Console.WriteLine(" locked =" + sw.Elapsed);


sw.Reset();

m_a = 0;

sw.Start();


for(int i = 0; i <10000000; ++ i)

{

Interlocked.Increment(ref m_a);

}


Console.WriteLine(" Interlocked =" + sw.Elapsed);


sw.Reset();

}

static void Main(string [] args)

{

程序p =新程序();

p.Test();

}

}

}





DanGo写道:

我的运行以下代码的结果:

基线= 00:00:00.0318235
volatile_int = 00:00:00.0320384 内存障碍= 00:00:01.1449614
VolatileMethods = 00:00:02.3170651
已锁定= 00:00:00.4858723
已互锁= 00:00:00.0907154




请注意,使用锁定比使用内存屏障快得多。


不锁定意味着内存屏障(顶部的读屏障和一个

底部的写屏障)由于锁定速度比一对内存障碍快4-5倍,比单个屏障快两倍。我们可以使用锁定

来代替对MemoryBarrier的调用。


如果一个不稳定的字段真的给我们一个障碍,它会快得多。在

中,它还为编译器提供了如何处理该字段的提示。




DanGo <沓*** @ discussions.microsoft.com>在消息中写道

新闻:EB ********************************** @ microsof t.com ...



DanGo写道:

我的运行以下代码的结果:

基线= 00:00:00.0318235
volatile_int = 00:00:00.0320384 内存障碍= 00:00:01.1449614
VolatileMethods = 00:00:02.3170651
已锁定= 00:00:00.4858723
已互锁= 00:00:00.0907154



请注意,使用锁定比使用内存屏障快得多。




您使用的是多处理器计算机吗?我在我的机器上运行了测试

得到了这些结果:


baseline = 00:00:00.0191971

volatile_int = 00 :00:00.0233645

内存障碍= 00:00:00.9672369

VolatileMethods = 00:00:01.9528108

已锁定= 00:00:01.7800082

Interlocked = 00:00:00.7257996

内存屏障比使用锁定要快得多。我不太清楚

的同步结构,但是如果只有一个处理器,那么锁实际上可能不会使用内存屏障。 />


Hi All,

I''m trying to get my head around synchronization.

Documentation seems to say that creating a volatile field gives a
memorybarrier.

Great! But when I do a little performance testing Thread.MemoryBarrier is
40 times slower than accessing a volatile int. Also I don''t see any
significant difference between the time to increment a volatile int and a
non-volatile int.

Could the difference all be attributable to the overhead of a function call?

When I read documentation on Thread.VolatileWrite it says that all other
processors are guaranteed to see your write immediately.

But when I use reflector to decompile VolatileWrite I get:

public static void VolatileWrite(ref int address, int value)
{
Thread.MemoryBarrier();
address = value;
}

Now if the MemoryBarrier is before the write couldn''t I throw the
MemoryBarrier on processor1 read value (through the cache) on processor 2 and
then write to address on processor 1 now the next read of address on
processor2 gets its "cached" value from before the new write.

(Boy it''s as hard to write about this stuff as it is to read).
processor1: Thread.MemoryBarrier
processor2: read address getting old_value (old_value cached)
processor1: address = new_value
processor2: read address still returning old_value.

VolatileWrite the way it is written seems to guarantee that any write before
it will get to main memory before this write but makes no guarantees about
this write.

Thanks

解决方案

My Results of running following code:

baseline = 00:00:00.0318235
volatile_int = 00:00:00.0320384
Memory Barriers = 00:00:01.1449614
VolatileMethods = 00:00:02.3170651
locked = 00:00:00.4858723
Interlocked = 00:00:00.0907154

Code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Threading;

namespace ConsoleApplication1
{
class Program
{
private object _syncobj = new Object();
private int m_a;
private volatile int m_v;

public void Test()
{
Stopwatch sw = new Stopwatch();

m_a = 0;
sw.Start();
for (int i = 0; i < 10000000; ++i)
m_a++;

Console.WriteLine("baseline = " + sw.Elapsed);

sw.Reset();
m_v = 0;
sw.Start();
for (int i = 0; i < 10000000; ++i)
m_v++;

Console.WriteLine("volatile_int = " + sw.Elapsed);

sw.Reset();
m_v = 0;
sw.Start();
for (int i = 0; i < 10000000; ++i)
{
// Thread.MemoryBarrier();
m_v++;
Thread.MemoryBarrier();
}

Console.WriteLine("Memory Barriers = " + sw.Elapsed);

sw.Reset();
m_a = 0;
sw.Start();
for (int i = 0; i < 10000000; ++i)
Thread.VolatileWrite(ref m_a, Thread.VolatileRead(ref m_a)+1);

Console.WriteLine("VolatileMethods = " + sw.Elapsed);

sw.Reset();
m_a = 0;
sw.Start();

for (int i = 0; i < 10000000; ++i)
{
lock(_syncobj)
{
m_a++;
}
}

Console.WriteLine("locked = " + sw.Elapsed);

sw.Reset();
m_a = 0;
sw.Start();

for (int i = 0; i < 10000000; ++i)
{
Interlocked.Increment(ref m_a);
}

Console.WriteLine("Interlocked = " + sw.Elapsed);

sw.Reset();
}
static void Main(string[] args)
{
Program p = new Program();
p.Test();
}
}
}




"DanGo" wrote:

My Results of running following code:

baseline = 00:00:00.0318235
volatile_int = 00:00:00.0320384
Memory Barriers = 00:00:01.1449614
VolatileMethods = 00:00:02.3170651
locked = 00:00:00.4858723
Interlocked = 00:00:00.0907154



Note that using a lock is considerably faster than using a memorybarrier.

Doesn''t a lock imply a memory barrier ( a read barrier at the top and a
write barrier at the bottom) Since the lock is 4-5 times faster than a pair
of memory barriers and twice as fast as a single barrier. We could use lock
in place of calls to MemoryBarrier.

If a volatile field really gives us a barrier it is much faster. In
addition it also gives the compiler hints on how to treat the field.



"DanGo" <Da***@discussions.microsoft.com> wrote in message
news:EB**********************************@microsof t.com...



"DanGo" wrote:

My Results of running following code:

baseline = 00:00:00.0318235
volatile_int = 00:00:00.0320384
Memory Barriers = 00:00:01.1449614
VolatileMethods = 00:00:02.3170651
locked = 00:00:00.4858723
Interlocked = 00:00:00.0907154



Note that using a lock is considerably faster than using a memorybarrier.



Are you using a multiple processor machine? I ran your test on my machine
and got these results:

baseline = 00:00:00.0191971
volatile_int = 00:00:00.0233645
Memory Barriers = 00:00:00.9672369
VolatileMethods = 00:00:01.9528108
locked = 00:00:01.7800082
Interlocked = 00:00:00.7257996

Memory Barrier is considerably faster than using a lock. I don''t know the
synchronization structure well, but its possible that lock doesn''t actually
use a memory barrier if there is only one processor.


这篇关于MemoryBarrier vs volatile vs lock的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆