Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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线程一致性问题_Java_Multithreading_Synchronized - Fatal编程技术网

Java线程一致性问题

Java线程一致性问题,java,multithreading,synchronized,Java,Multithreading,Synchronized,我在一个小代码示例中复制了一个用例: package com.learning.thread; public class ThreadInterupt { public volatile int count; public synchronized int getCount() { return count; } public void setCount(int count) { this.count = count;

我在一个小代码示例中复制了一个用例:

package com.learning.thread;

public class ThreadInterupt {
    public volatile int count;

    public synchronized int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
    public synchronized void increment(){
        count++;
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadInterupt local = new ThreadInterupt();
        Thread firstThread = new Thread( new myThread(local));
        Thread secondThread = new Thread( new myThread(local));

        firstThread.start();
        secondThread.start();

        Thread.sleep(10);
        firstThread.interrupt();
        secondThread.interrupt();

    }
}

class myThread implements Runnable{
    static void threadMessage(String message) {
        String threadName =
            Thread.currentThread().getName();
        System.out.format("%s: %s%n",
                          threadName,
                          message);
    }

    ThreadInterupt global;

    public  myThread(ThreadInterupt local){
        global = local;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        int i=0;
        while(i<5){
            if(Thread.interrupted()){
                threadMessage("Got Killed");
                break;
            }
            i++;
            global.increment();
            threadMessage(String.valueOf(global.getCount()));
        }
    }
}
正如您在线程0打印7后看到的,线程1打印4。我在这里的假设是线程1进入了同步方法get,并被线程0的增量方法阻塞,一旦线程0完成,它就会打印出get。我不相信这一点。有人能帮忙吗

//编辑,正如codeBencher所建议的

这可能是因为延误。当我将同步打印方法添加到ThreadInterupt类中时,效果很好

public synchronized void print(String threadName){
  System.out.println(threadName+String.valueOf(count));
 }
以及在运行中的方法

global.increment();
global.print(Thread.currentThread().getName());

这是一个比赛条件。JVM不能保证每个线程有多少个周期。因此,volatile起作用了,因为您不会看到相同的数字显示两次。但是,跨两个线程执行命令的顺序并不像您预期的那样。它没有变为t-1执行命令,现在t-2执行命令,现在t-1再次执行命令,现在t-2执行命令。相反,它可能已经做到了t-1,t-1,t-1,t-2,t-1,t-2,t-2,t-2,t-2,t-2。。。。等等等等。迫使它进入t-1,t-2,t-1,t-2。。按照这个顺序,您必须使用其他技术来使用中的类


例如,一种常见的技术是使用ConcurrentLatch或Future等待一个或多个其他线程完成。一个非常酷的方法可能适用于这样的倒计时(或倒计时)系统,其中t-1和t-2可以分别递增一个可变整数,然后等待CyclicBarrier让它们继续。

嗯,线程可以在调用
increment
后但在调用
getCount()之前中断
。在您的
global.getCount()
System.out.format()之间有很多语句。当thread1出现在这些语句中时,执行可能会移动到thread0。这是一个典型的竞争条件的好例子。仅同步单个操作是不够的。你必须确保你期望的行为同步发生。我认为@Codebender,你是对的。编辑答案我希望你意识到你在这里看到的行为与中断无关。您可以去掉示例的这一部分,其行为将是相同的。我总是只有两个线程,它们都使用变量并修改它。我会调查这件事的
global.increment();
global.print(Thread.currentThread().getName());