Java和C#中的可变语义背后的原因是什么 - c#

C#和Java都定义了
* 易失性读取具有语义
* 易失性写入具有释放语义

我的问题是:

  • 这是定义volatile的唯一正确方法。
  • 如果不是,如果语义相反,情况会完全不同吗?
  • 易失性读取具有释放语义
  • 易失性写入具有语义
  • 参考方案

    volatile语义背后的推理源于Java Memory Model,它是根据操作指定的:

  • 读取和写入变量
  • 锁定和解锁监视器
  • 以线程
  • 开始和加入

    Java内存模型在之前为Java程序中可能发生的动作定义了一个称为发生的partial ordering。通常,不能保证线程可以看到其他操作的结果。

    假设您有两个动作 A B 。为了保证执行操作B的线程可以看到操作A的结果,必须在A和B之间的关系之前发生。如果没有,则JVM可以随意按自己的喜好对重新排序

    未正确同步的程序可能会出现数据争用。当变量被> 1个线程读取并由> = 1个线程写入时,发生数据争用,但是读写操作未通过“先发生后先排序”进行排序。

    因此,正确同步的程序没有数据争用,并且程序内的所有操作均以固定顺序发生。

    因此,操作通常仅按的一部分的顺序进行排序,但在以下之间还存在的总顺序:

  • 锁定获取并释放
  • 读写易失性变量
  • 这些动作是完全有序的。

    这使得在“随后的”锁获取和易失性变量的读取之前描述发生是明智的。

    关于您的问题:

  • 使用事前发生关系,您可以选择volatile的替代定义
  • 颠倒顺序对上面的定义没有意义,尤其是因为涉及到总顺序。
  • 这说明了两个线程使用公用的进行同步时的事前发生关系。线程A中的所有操作都按照程序顺序规则进行排序,因为线程B中的操作也是如此。由于A释放了锁M,B 随后获得了M,因此释放锁之前A中的所有操作都被了在获得锁之后,在之前执行B中的操作。当两个线程在不同的锁上同步时,我们无法说出它们之间的动作顺序,因此在两个线程之间的动作之间没有任何关联。

    资料来源:Java Concurrency in Practice

    我的java线程占用多少内存? - java

    有没有办法找出我的Java线程在虚拟机中占用多少内存?例如,使用堆栈跟踪转储或其他某种方式。谢谢 参考方案 Java线程将堆用作共享内存。各个线程都有其堆栈(可以通过-Xss命令行选项设置大小,默认为512KB),但是所有其他内存(堆)都不属于特定线程,并询问一个特定线程使用了多少内存根本没有道理。

    如何从线程返回值(java) - java

    我做了这样的一个波纹管:public class MyThread implements Runnable { private int temp; public MyThread(int temp){ this.temp=temp; } @Override public void run() { temp+=10; return; } public int …

    Java:线程池如何将线程映射到可运行对象 - java

    试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

    JAVA:字节码和二进制有什么区别? - java

    java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…

    java:继承 - java

    有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…