|
|
1
58
默认情况下,Java中的所有内存访问都是原子的,除非
从 section 17.4.3 JLS:
然后在 17.7 :
注意原子性和波动性是非常不同的。 当一个线程将一个整数更新为5时,它保证另一个线程不会看到1或4或任何其他处于中间状态的线程,但如果没有任何显式的波动性或锁定,另一个线程将永远看到0。 关于努力获得对字节的原子访问,你是对的:虚拟机可能需要努力…但这是必须的。从 section 17.6 规格:
换言之,这取决于JVM如何正确处理。 |
|
|
2
26
再往下走
这似乎意味着对ints的写入是原子的。 |
|
|
3
4
我认为这并不像你预期的那样有效:
整数是不可变的,所以您一直在同步处理不同的对象。 int“i”被自动框定为整数对象,然后在其上设置锁。 如果另一个线程进入这个方法int,我将被自动定位到另一个整型对象,并且您在另一个对象上设置了锁,那么之前。 |
|
|
4
4
我同意乔恩·斯基特的观点,我想补充一下,许多人混淆了原子性、波动性和线程安全的概念,因为有时术语可以互换使用。
虽然有人可能会说这个操作是原子的,但引用的假设是错误的。
因此,在这个变量上操作的线程应该像这样同步:
或者:
请注意,对于单个对象实例,调用正由多个线程访问并对共享可变数据进行操作的方法时,必须考虑到一个方法的参数、局部变量和返回值对于每个线程都是局部的这一事实。
有关详细信息,请查看此链接:
希望这有帮助。 更新 :也可以在类对象本身上进行同步。更多信息在这里: How to synchronize a static variable among threads running different instances of a class in java? |
|
|
5
3
从整数或任何更小的类型读取或写入应该是原子的,但是正如Robert所指出的,long和double可能取决于实现,也可能不取决于实现。然而,任何同时使用读和写的操作,包括所有的增量操作符,都不是原子的。因此,如果必须在整数i=0上运行线程,一个是i++,另一个是i=10,那么结果可能是1、10或11。 对于这样的操作,您应该看看 AtomicInteger 它具有在检索旧值时自动修改值或自动递增值的方法。 最后,线程可能会缓存变量的值,并且不会看到其他线程对它所做的更改。为了确保两个线程都能看到另一个线程所做的更改,需要将变量标记为易失性。 |
|
|
6
1
这不是原子的:
但是,这是:
我想这就是一些混乱的地方。 |
|
|
7
0
这有点复杂,并且与系统字大小有关。布鲁斯·埃克尔更详细地讨论了这个问题: Java Threads . |
|
|
8
0
原子读写仅仅意味着永远不会读,例如int更新的前16位和旧值的另一位。 这与其他线程何时看到这些写入无关。 长话短说的是,当两个线程竞争时,它们之间没有记忆障碍,就会丢失一些东西。 向上旋转两个或多个线程,这些线程会增加一个共享整数,并计算它们自己的增量。当整数达到某个值(例如int_max)时。很好,而且很大,可以让事情预热)停止一切,返回int的值和每个线程执行的增量。
下面是我的四核盒测试的结果(请随意使用代码中的线程计数,显然我只是匹配了我的核心计数):
|
|
|
9
0
在线程之间共享数据时,需要同步。当处理一个整数时,它可以从主内存转移到多处理器系统中的处理器缓存,线程可能正在更新绑定到特定处理器的整数的本地副本。 挥发性 (See Wiki in Java Section) Java中的关键字将确保对内存的任何更新都将发生在内存中,而不是本地副本。 此外,要将更新同步到整数,请考虑使用atomicinteger。此实现有一个方法 (compareAndSet) 检查一个值是否是线程期望的值,如果是,则设置该值。如果不匹配,那么另一个线程可能已经更新了该值。原子整数将在原子操作中执行整数的读取和更新,其优点是不必阻塞。 |
|
|
user107586 · 如何处理等待句柄不会导致无限循环? 1 年前 |
|
|
ron burgundy · 获取-释放语义是否跨线程传递?[副本] 1 年前 |
|
|
BenjiFB · C#内存缓存:在一次操作中追加到列表? 1 年前 |
|
|
András Takács · Python多线程问题 1 年前 |
|
|
András Takács · Python多线程错误 1 年前 |