这是一个场景
我们有两个线程都访问同一段代码,并且该代码有一个变量,例如
诠释a = 200;
线程 A 进入并将其值更改为 a=300;
然后线程 B 访问这个变量,线程 B 会得到 200 还是 300?
这是一个场景
我们有两个线程都访问同一段代码,并且该代码有一个变量,例如
诠释a = 200;
线程 A 进入并将其值更改为 a=300;
然后线程 B 访问这个变量,线程 B 会得到 200 还是 300?
不保证两个线程以任何固定顺序执行;A 中的任何操作都可以先于 B 中的任何操作(前提是这些操作仍然在它们自己的线程中按顺序流动)。
因此,如果没有同步,A 可能会在 B 访问它之前或之后更改它的值。如果 A 在 B 之前更改它,则 B 看到 300;否则,B 看到 200。
下面的状态图描述了线程状态。
Thread.sleep(milliseconds), Thread.sleep(milliseconds, nanoseconds);
关于您的示例,我们不知道哪个线程 B 将占用 200 或 300。如果您同时启动两个线程,因为您的方法将被同步,线程 B 应该看到 200(以防它是第一个或 300)。
由于编译器优化,线程可能会缓存数据,并且第二个线程可能看不到第一个线程的更改。这就是将“volatile”用于共享数据以避免多线程环境中的问题的地方
附录-嗯,我说的是跨线程的变量更改的可见性,而不是同步。
如果您的线程同时访问您的一段代码,它将根据 jvm 级别的线程优先级发生。我们不能保证哪个线程将访问代码。如果是同步的,线程 B 必须等到线程 A 释放资源。
上述执行的结果取决于一致性模型。
在顺序一致性模型中,执行的结果是所有指令都以某种全局顺序执行。在这种情况下,threadB 将获得值 300。
但是,现代机器使用较弱的一致性模型,其中所有同步(内存围栏指令)操作单独以全局顺序发生。
如果线程 B 的负载发生在线程 A 的存储完成之后,线程 B 将获得值 = 300。这是由缓存一致性协议保证的。但是,如果线程 B 的加载指令发生在线程 A 的存储之前/同时发生(由于某些优化),则线程 B 中的共享变量的值是未定义的。这将是线程B的加载和线程A的存储之间通过总线操作竞争条件的结果。