readonly成员的线程安全 [英] Thread safety of readonly members

查看:66
本文介绍了readonly成员的线程安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在文档中的线程

部分找不到关于此的声明...


考虑:


class Class1

{

Class1()

{

_val = 42;

}


public int getVal()

{

return _val;

}


private readonly int _val;

}


在线程环境中,是否有必要在构造函数和getVal()内部互锁

以确保

线程获得正确的值?换句话说,

我必须写如下吗?


class Class1

{

Class1()

{

lock(this)

{

_val = 42;

}

}


public int getVal()

{

lock (这)

{

返回_val;

}

}


private readonly int _val;

}


在C ++中,锁定是必要的,因为在SMP

机器上,如果没有

锁定,则不保证内存一致性。但是我不知道是否也是如此。

for C#。


如果成员变量不是只读的话会怎样(但是会是

永远不会被修改,除了初始赋值

在构造函数中)?在这种情况下,没有锁定访问值线程安全




const成员怎么样?如果没有

就可以访问这些安全锁吗?


那么(概念上)静态成员怎么样?b $ b不可变?那里需要锁吗?


非常感谢,


Michi。

Hi, I can''t find a statement about this in the threading
sections in the doc...

Consider:

class Class1
{
Class1()
{
_val = 42;
}

public int getVal()
{
return _val;
}

private readonly int _val;
}

In a threaded environment, is it necessary to interlock
inside the constructor and getVal() to ensure that
threads get the correct value? In other words,
do I have to write it as follows?

class Class1
{
Class1()
{
lock(this)
{
_val = 42;
}
}

public int getVal()
{
lock(this)
{
return _val;
}
}

private readonly int _val;
}

In C++, the lock is necessary because, on SMP
machines, memory consistency isn''t guaranteed without
the lock. But I don''t know whether the same is true
for C#.

What if the member variable is not readonly (but will
never be modified, except for the initial assignment
in the constructor)? Is accessing the value thread-safe
without a lock in that case?

What about const members? Is access to those safe without
a lock?

And what about static members that are (conceptually)
immutable? Is the lock required there?

Thanks muchly,

Michi.

推荐答案

" Michi Henning" < MI *** @ zeroc.com>在消息中写道

news:eq ************** @ TK2MSFTNGP12.phx.gbl ...
"Michi Henning" <mi***@zeroc.com> wrote in message
news:eq**************@TK2MSFTNGP12.phx.gbl...
在线程环境中,是否有必要在构造函数和getVal()内部互锁以确保
线程获得正确的值?换句话说,我必须按如下方式编写吗?


在你给出的具体例子中,由于一些原因,没有必要。


因为你所拥有的只是构造函数和getVal (),共享资源从来没有任何

竞争。当构造对象时,

还没有人引用它,所以没有人可以调用getVal()。你可以确保任何调用getVal()的人在构造函数

完成执行后调用它。


数据永远不会处于不一致状态,因为它只是一个单独的
int。 Ints是原子分配的。我不确定其他类型 - 我是

确定结构没有原子分配,但我不肯定

数字是> 32位(我怀疑它们不是原子的 - 也许某人

可以清除它)。假设我们添加一个putVal()方法来使事情复杂化。

假设有人在有人调用

getVal()的同时调用putVal(0)。他们会得到什么?好吧,他们会得到42或0.锁定

并没有改变它。

在C ++中,锁是必要的,因为在SMP上
机器,没有锁定就不能保证记忆的一致性。但我不知道C#是否也是如此。


在C ++中也是如此,C#也是如此。你的

具体例子并不需要同时使用任何一种语言进行同步,但是我知道你可能只是想简化帖子的内容。

如果成员变量不是只读的(但是除了构造函数中的初始赋值之外,它将永远不会被修改),该怎么办?在这种情况下,没有锁定访问值线程安全



是的。

const成员怎么样?没有锁定可以访问那些安全吗?


是的。

那些(概念上)不可变的静态成员呢?那里需要锁?
In a threaded environment, is it necessary to interlock
inside the constructor and getVal() to ensure that
threads get the correct value? In other words,
do I have to write it as follows?
In the specific example you gave, it is not necessary, for a few reasons.

Since all you have is the constructor and getVal(), there is never any
competition for the shared resource. When the object is being constructed,
nobody has a reference to it yet, so nobody can call getVal(). You can be
sure that anybody calling getVal() will be calling it after the constructor
has finished executing.

The data can never be in an inconsistent state since it is just a single
int. Ints are assigned atomically. I''m not sure about other types - I am
sure that structs are not assigned atomically, but I''m not positive about
numbers that are > 32 bits (I suspect they are not atomic - perhaps someone
can clear this up). Suppose we add a putVal() method to complicate things.
Suppose that someone calls putVal(0) around the same time someone calls
getVal(). What will they get? Well, they will either get 42 or 0. A lock
doesn''t change that.
In C++, the lock is necessary because, on SMP
machines, memory consistency isn''t guaranteed without
the lock. But I don''t know whether the same is true
for C#.
In the cases where this is true of C++, it is also true of C#. Your
specific example doesn''t require synchronization in either language, but I
realize you were probably just trying to simplify things for your post.
What if the member variable is not readonly (but will
never be modified, except for the initial assignment
in the constructor)? Is accessing the value thread-safe
without a lock in that case?
Yes.
What about const members? Is access to those safe without
a lock?
Yes.
And what about static members that are (conceptually)
immutable? Is the lock required there?




在这种情况下也不需要锁。


我不确定你的如果您对

多线程编程有基本的了解,请发布。大多数语言的原则都是一样的。

如果你不确定,我建议你就这个话题做一些阅读。


HTH
Mike



No lock required in this case either.

I''m not sure from your post if you have a basic understanding of
multithreaded programming. The principles are the same in most languages.
If you are unsure, I''d suggest doing some reading on that topic.

HTH
Mike


Re:;类型的不规则性。规范的第5.5节读取:


5.5变量引用的原子性


以下数据类型的读写是原子的:bool,char ,byte,

sbyte,short,ushort,uint,int,float和reference types。另外,

读取和写入前一个列表中具有基础类型的枚举类型

也是原子的。读取和写入其他类型,包括long,ulong,

double和decimal,以及用户定义的类型,不保证是原子的
。除了为此目的设计的库函数之外,还有

无法保证原子读 - 修改 - 写,例如在增量

或减量的情况下。 />

Richard

-

C#,.NET和复杂适应系统:
http://blogs.geekdojo.net/Richard

" Michael Sparks" < MI ************ @ remove.this.sbcglobal.net>在留言中写道

news:yB ***************** @ newssvr23.news.prodigy.co m ...
Re:; the atmomicity of types. Section 5.5 of the spec reads:

5.5 Atomicity of variable references

Reads and writes of the following data types are atomic: bool, char, byte,
sbyte, short, ushort, uint, int, float, and reference types. In addition,
reads and writes of enum types with an underlying type in the previous list
are also atomic. Reads and writes of other types, including long, ulong,
double, and decimal, as well as user-defined types, are not guaranteed to be
atomic. Aside from the library functions designed for that purpose, there is
no guarantee of atomic read-modify-write, such as in the case of increment
or decrement.

Richard
--
C#, .NET and Complex Adaptive Systems:
http://blogs.geekdojo.net/Richard
"Michael Sparks" <mi************@remove.this.sbcglobal.net> wrote in message
news:yB*****************@newssvr23.news.prodigy.co m...
Michi Henning < MI *** @ zeroc.com>在消息中写道
新闻:eq ************** @ TK2MSFTNGP12.phx.gbl ...
"Michi Henning" <mi***@zeroc.com> wrote in message
news:eq**************@TK2MSFTNGP12.phx.gbl...
在线程环境中,是否有必要在构造函数和getVal()内部互锁
以确保
线程获得正确的值?换句话说,我必须按如下方式编写它吗?
在你给出的具体例子中,由于一些原因,没有必要。

因为你有所有是构造函数和getVal(),共享资源永远不会有任何竞争。当对象构造
In a threaded environment, is it necessary to interlock
inside the constructor and getVal() to ensure that
threads get the correct value? In other words,
do I have to write it as follows?
In the specific example you gave, it is not necessary, for a few reasons.

Since all you have is the constructor and getVal(), there is never any
competition for the shared resource. When the object is being



时,没有人引用它,所以没有人可以调用getVal()。您可以确保任何调用getVal()的人都会在
构造函数执行完毕后调用它。

数据永远不会处于不一致状态,因为它只是单个
int。 Ints是原子分配的。我不确定其他类型 - 我确定结构不是原子分配的,但我不是肯定的
数字是> 32位(我怀疑它们不是原子的 - 也许
有人可以清除它)。假设我们添加一个putVal()方法来复杂
的东西。假设有人在调用
getVal()的同时调用putVal(0)。他们会得到什么?好吧,他们要么得到42或者0.
锁定不会改变它。


constructed, nobody has a reference to it yet, so nobody can call getVal(). You can be
sure that anybody calling getVal() will be calling it after the constructor has finished executing.

The data can never be in an inconsistent state since it is just a single
int. Ints are assigned atomically. I''m not sure about other types - I am
sure that structs are not assigned atomically, but I''m not positive about
numbers that are > 32 bits (I suspect they are not atomic - perhaps someone can clear this up). Suppose we add a putVal() method to complicate things. Suppose that someone calls putVal(0) around the same time someone calls
getVal(). What will they get? Well, they will either get 42 or 0. A lock doesn''t change that.

在C ++中,锁是必要的,因为在SMP上
机器,没有锁定就不能保证记忆的一致性。但我不知道C#是否也是如此。
In C++, the lock is necessary because, on SMP
machines, memory consistency isn''t guaranteed without
the lock. But I don''t know whether the same is true
for C#.



在C ++中也是如此,C#也是如此。你的具体例子并不需要用任何一种语言进行同步,但我意识到你可能只是想简化帖子的内容。



In the cases where this is true of C++, it is also true of C#. Your
specific example doesn''t require synchronization in either language, but I
realize you were probably just trying to simplify things for your post.

如果成员变量不是只读的(但是除了构造函数中的初始赋值之外,它将永远不会被修改)?在没有锁的情况下访问值是线程安全的吗?
What if the member variable is not readonly (but will
never be modified, except for the initial assignment
in the constructor)? Is accessing the value thread-safe
without a lock in that case?



是的。



Yes.

const成员怎么样?是否可以在没有锁定的情况下访问这些?
What about const members? Is access to those safe without
a lock?



是的。



Yes.

那么静态成员(概念上)<不可变的?那里需要锁吗?
And what about static members that are (conceptually)
immutable? Is the lock required there?



在这种情况下也不需要锁定。

我不确定你的帖子是否基本了解
多线程编程。大多数语言的原则都是一样的。
如果你不确定,我建议你就这个话题做一些阅读。

HTH
Mike



No lock required in this case either.

I''m not sure from your post if you have a basic understanding of
multithreaded programming. The principles are the same in most languages.
If you are unsure, I''d suggest doing some reading on that topic.

HTH
Mike



Michael Sparks< mi ************ @ remove.this.sbcglobal.net>写道:
Michael Sparks <mi************@remove.this.sbcglobal.net> wrote:
在你给出的具体例子中,由于一些原因,没有必要。

因为你所拥有的只是构造函数和getVal(),所以从来没有对共享资源的任何竞争。在构造对象时,没有人引用它,所以没有人可以调用getVal()。你可以确保任何调用getVal()的人都会在构造函数完成执行后调用它。
In the specific example you gave, it is not necessary, for a few reasons.

Since all you have is the constructor and getVal(), there is never any
competition for the shared resource. When the object is being constructed,
nobody has a reference to it yet, so nobody can call getVal(). You can be
sure that anybody calling getVal() will be calling it after the constructor
has finished executing.




那不是确实如此。不幸的是,编译器内存

重新排序最终可能会出现伪代码:


线程1:

o创建新的空对象

o商店参考

o呼叫构造函数


第二个和第三个部分之间可以有第二个线程,并且

在参考上调用getVal。


基本上,除非你有内存围栏,否则我相信

编译器是免费的做任何它喜欢的重新排序,所以

只要每个单独的线程看到与自身一致的东西。


它只是理论上的,我强烈怀疑在任何当前的CLR实施中都不会发生b $ b b,但我相信这是* * b $ b潜在的问题。实际上,问题是引用本身如何显示 - 如果引用是在锁中分配的(并且同一个锁是

,这是第一次访问它),一切都会好的。


当然,我可能完全错了,但这就是我对b
理解它的方式。 。


-

Jon Skeet - < sk *** @ pobox.com>
http://www.pobox.com/~skeet

如果回复该群组,请不要给我发邮件



That''s not quite true, actually. Unfortunately, compiler memory
reordering could end up with the pseudocode of:

Thread 1:
o Create new "empty" object
o Store reference
o Call constructor

A second thread could come in between the second and third parts, and
call getVal on the reference.

Basically, unless you''ve got memory fences involved, I believe the
compiler is free to do whatever it likes in terms of reordering, so
long as each individual thread sees something consistent with itself.

It''s only theoretical, and I strongly suspect that it would never
happen on any current CLR implementation, but I believe it *is* a
potential problem. Effectively, the issue is how the reference itself
is visible - if the reference is assigned in a lock (and the same lock
is required to access it for the first time), all would be well.

Of course, I could be entirely wrong about this, but that''s the way I
understand it...

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


这篇关于readonly成员的线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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