Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java原语ints是设计的还是偶然的?_Java_Multithreading - Fatal编程技术网

java原语ints是设计的还是偶然的?

java原语ints是设计的还是偶然的?,java,multithreading,Java,Multithreading,就这点而言,java原始整数(int)是原子的吗?对共享int的两个线程进行的一些实验似乎表明它们是,但当然,没有证据表明它们不是,并不意味着它们是 具体来说,我进行的测试是: public class IntSafeChecker { static int thing; static boolean keepWatching = true; // Watcher just looks for monotonically increasing values

就这点而言,java原始整数(int)是原子的吗?对共享int的两个线程进行的一些实验似乎表明它们是,但当然,没有证据表明它们不是,并不意味着它们是

具体来说,我进行的测试是:

public class IntSafeChecker {
    static int thing;
    static boolean keepWatching = true;

    // Watcher just looks for monotonically increasing values   
    static class Watcher extends Thread {
        public void run() {
            boolean hasBefore = false;
            int thingBefore = 0;

            while( keepWatching ) {
                // observe the shared int
                int thingNow = thing;
                // fake the 1st value to keep test happy
                if( hasBefore == false ) {
                    thingBefore = thingNow;
                    hasBefore = true;
                }
                // check for decreases (due to partially written values)
                if( thingNow < thingBefore ) {
                    System.err.println("MAJOR TROUBLE!");
                }
                thingBefore = thingNow;
            }
        }
    }

    // Modifier just counts the shared int up to 1 billion
    static class Modifier extends Thread {
        public void run() {
            int what = 0;
            for(int i = 0; i < 1000000000; ++i) {
                what += 1;
                thing = what;
            }
            // kill the watcher when done
            keepWatching = false;
        }
    }

    public static void main(String[] args) {
        Modifier m = new Modifier();
        Watcher w = new Watcher();
        m.start();
        w.start();
    }
}
公共类IntSafeChecker{
静态整数事物;
静态布尔值keepWatching=true;
//Watcher只是寻找单调递增的值
静态类观察程序扩展线程{
公开募捐{
布尔hasBefore=false;
int thingBefore=0;
同时(继续观察){
//观察共享int
int thingNow=事物;
//伪造第一个值以使测试满意
if(hasBefore==false){
thingBefore=thingNow;
hasBefore=真;
}
//检查是否减少(由于部分写入值)
if(thingNow
(这仅在32位windows PC上使用java jre 1.6.0_07进行了尝试)

本质上,修饰符将一个计数序列写入共享整数,同时观察者检查观察值是否从未减少。在一台32位值必须作为四个独立字节(甚至两个16位字)访问的机器上,观察者很可能会捕获处于不一致、半更新状态的共享整数,并检测到值的减少而不是增加。无论(假设的)数据字节是收集/写入LSB 1st还是写入MSB 1st,这都应该有效,但充其量只是概率性的

考虑到当今广泛的数据路径,32位值很可能是有效的原子值,即使java规范不需要它。事实上,使用32位数据总线,您可能需要比使用32位整数更努力地获得对字节的原子访问

在“java primitive thread safety”(java primitive thread safety)上搜索会发现线程安全类和对象上的大量内容,但查找这些原语的信息似乎是大海捞针。

  • 再多的测试也不能证明线程的安全性——它只能证明它是错误的
  • 我发现了一个间接引用,其中
一些实现可能会发现,将64位长或双精度值上的单个写入操作划分为相邻32位值上的两个写入操作非常方便

再往下

对于Java编程语言内存模型而言,对非易失性长或双值的单次写入被视为两次单独的写入:每32位半写一次


这似乎意味着对int的写入是原子的。

这有点复杂,并且与系统字数有关。Bruce Eckel对此进行了更详细的讨论:.

默认情况下,Java中的所有内存访问都是原子的,除了
long
double
(可能是原子的,但不一定是原子的)。老实说,这并没有说得很清楚,但我相信这就是其中的含义

来自JLS的:

在顺序一致的 执行时,有一个总订单已结束 所有单个操作(如读取 并写入)这与 程序的顺序,以及每个 个人行动是原子的,是独立的 每根线都能立即看到

然后在:

一些实现可能会找到它 很方便地分割一次写入 对64位长或双精度文件执行操作 将值转换为上的两个写入操作 相邻的32位值。对于 为了提高效率,这种行为是错误的 具体实施;Java虚拟 机器可以自由地执行写入操作 长值和双值原子或 分为两部分

注意原子性和波动性是非常不同的

当一个线程将一个整数更新为5时,可以保证另一个线程不会看到1、4或任何其他中间状态,但如果没有任何显式的波动性或锁定,另一个线程可能永远看到0

关于努力获得字节的原子访问权,你是对的:虚拟机可能需要努力。。。但这是必须的。从规范的第一部分:

某些处理器不提供 能够写入单个字节。信息技术 实现字节是非法的 在这样的处理器上通过 简单地读一个单词, 更新适当的字节,以及 然后把整个单词写回 记忆。这个问题有时很难解决 被称为单词撕裂,等等 无法轻松更新数据的处理器 孤立的单字节 这需要一种方法


换句话说,由JVM来决定是否正确。

从整数或任何较小的类型进行读取或写入应该是原子的,但正如Robert所指出的,long和double可能取决于实现,也可能不取决于实现。但是,任何同时使用读取和写入的操作,包括所有增量运算符,都不是原子操作。因此,如果必须对整数i=0执行操作,一个执行i++操作,另一个执行i=10操作,则结果可能是1、10或11

对于这样的操作,您应该了解在检索旧值时,哪些方法具有原子修改值的方法
private static int i = 0;
public void increment() { i++; }
private static int i = 0;
private static final Object LOCK = new Object();
public void increment() {
   synchronized(LOCK) {
       i++;
    } 
}
private static int i = 0;
public static synchronized void increment() {
   i++; 
}
private static int i = 0;
public void increment() {
   synchronized (i) { 
      i++; 
   }
}
    import java.util.Stack;

public class Test{

  static int ctr = Integer.MIN_VALUE;
  final static int THREADS = 4;

  private static void runone(){
    ctr = 0;
    Stack<Thread> threads = new Stack<>();
    for(int i = 0; i < THREADS; i++){
      Thread t = new Thread(new Runnable(){
        long cycles = 0;

        @Override
        public void run(){
          while(ctr != Integer.MAX_VALUE){
            ctr++;
            cycles++;
          }
          System.out.println("Cycles: " + cycles + ", ctr: " + ctr);
        }
      });
      t.start();
      threads.push(t);
    }
    while(!threads.isEmpty())
      try{
        threads.pop().join();
      }catch(InterruptedException e){
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    System.out.println();
  }

  public static void main(String args[]){
    System.out.println("Int Range: " + ((long) Integer.MAX_VALUE - (long) Integer.MIN_VALUE));
    System.out.println("  Int Max: " + Integer.MAX_VALUE);
    System.out.println();
    for(;;)
      runone();
  }
}
Int Range: 4294967295
Int Max: 2147483647

Cycles: 2145700893, ctr: 76261202
Cycles: 2147479716, ctr: 1825148133
Cycles: 2146138184, ctr: 1078605849
Cycles: 2147282173, ctr: 2147483647

Cycles: 2147421893, ctr: 127333260
Cycles: 2146759053, ctr: 220350845
Cycles: 2146742845, ctr: 450438551
Cycles: 2146537691, ctr: 2147483647

Cycles: 2110149932, ctr: 696604594
Cycles: 2146769437, ctr: 2147483647
Cycles: 2147095646, ctr: 2147483647
Cycles: 2147483647, ctr: 2147483647

Cycles: 2147483647, ctr: 330141890
Cycles: 2145029662, ctr: 2147483647
Cycles: 2143136845, ctr: 2147483647
Cycles: 2147007903, ctr: 2147483647

Cycles: 2147483647, ctr: 197621458
Cycles: 2076982910, ctr: 2147483647
Cycles: 2125642094, ctr: 2147483647
Cycles: 2125321197, ctr: 2147483647

Cycles: 2132759837, ctr: 330963474
Cycles: 2102475117, ctr: 2147483647
Cycles: 2147390638, ctr: 2147483647
Cycles: 2147483647, ctr: 2147483647
i++;
i = 5;