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());