Java多线程跳过循环并给出错误的结果
package Threading;
class DemoThread extends Thread{ //Thread Class
static int count=0; // variable incremented by both the threads
public DemoThread(String name) {
// TODO Auto-generated constructor stub
super(name);
}
public void run() {
for(int i=0;i<100000;i++) {
count++;
System.out.println(Thread.currentThread()+"Count"+count); // print thread operating on count variable
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class MyThreadClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
DemoThread t1=new DemoThread("T1");
DemoThread t2=new DemoThread("T2");
t1.start();
t2.start();
try {
t1.join();
t2.join(); //allowing both the threads to complee before main thread
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Main Thread ends"+DemoThread.count); //final value of count
}
}
计数的最终值应该是199998,但它没有给出期望的结果。为什么线程缺少循环???
问题
在Java中,多线程将异步行为引入到程序中,需要时必须强制执行同步性。
如果没有同步,没有任何东西可以阻止要访问的线程在同一时间对同一对象调用同一方法。这被称为竞争条件,因为线程正在相互竞争以完成该方法。
输出的第一行打印了2!?这是因为t1写了Count的值,并且在打印它之前就被抢占了。请注意,要抢占线程,它不需要进入Hibernate状态。操作系统仍然这样做。
如果您注意到1st行和4th行,您可以看到不一致。这种不一致性在大型程序中变得不可预测。
以下是多次运行的最终结果。
不应该想当然地认为总是产生错误的结果,不,有时产生正确的结果,它意味着结果将是不可预测的。
对的误解?
线程跳过循环。!?不,线程没有跳过循环。不同的线程访问相同的值,但在它可以写入自己的值之前,其他线程写入该值并继续。因此,当它下次访问该值时,它选择了错误的值。
这就是所谓的读者作家问题
解决方案
在程序中,t1和t2使用不同的值访问计数变量。为了防止其他线程在其他线程完成之前调用run(),我们在方法之前添加了一个synchronized关键字。
synchronized public void run(){}
同步关键字保护状态免受竞争条件的影响。一旦一个线程进入同步方法,其他线程不允许使用该方法,直到前一个线程退出该方法。
这是由于同步关键字的正确输出。注意:我用200作为循环的结尾。
奖金
如果您使用的专有方法将共享数据作为输入。可以使用同步块
synchronized(objRef){
//Method calling
}
objRef是正在同步的对象的引用。
如评论
中推荐的[推荐解决方案]
您应该使用原子整数而不是本机int。使用java.util.concurrent.atomic
包。
参考java.util.concurrent.atomic
而不是静态int计数=0;
使用静态原子整数计数=新的原子整数(0);
而不是计数;
使用count.incrementAndGet();
原子整数是固有的同步。
原子整数参考Java文档
您必须使用java.util.concurrent.atomic.原子整数,而不是共享的静态int变量。
之所以发生这种情况,是因为线程T1和T2将同时更新count
,如下所示:
Thread[T1,5,main]Count10
Thread[T2,5,main]Count10
Thread[T1,5,main]Count12
Thread[T2,5,main]Count12
Thread[T2,5,main]Count14
Thread[T1,5,main]Count14
Thread[T1,5,main]Count15
Thread[T2,5,main]Count16
你应该使用原子整数
并更新您的代码:
static int count=0
tostatic AtomicInteger count=new AtomicInteger()
计数
到<代码>计数。incrementAndGet()
你好,我试图跳过一些错误消息并通过将空csv写入我的工作d目录来继续循环。 问题是没有is。我知道的错误()?我不知道如何实现try()包装器来获得所需的结果。
问题内容: 根据Wolfram Mathematica: cos(50) = 0.6427876096865394 ; 但是这段Java代码: 给出 0.9649660284921133 。 有什么问题吗? 问题答案: 期望参数以弧度为单位。这将返回您需要的结果:
在下面的代码: 在上面的代码中,我从用户那里得到一个表名列表,然后在for循环中对它们进行迭代。代码正在工作,但它没有将数据插入临时表并以错误结束。 错误: 请帮我找出为什么会出现这个错误?
我有一个方法getCount(id),它从数据库返回一个整数,作为CompletableFuture。我想遍历所有id,并获得所有它们的结果,并将它们添加到一个全局int。然后我想用那个int做些事情: 这会给出一个错误,因为您不能在Accept中将一个整数添加到另一个整数,因为它是一个消费者。怎么做?
我在两个特征类中有两个几何,一个名为“HY90299”,另一个名为“hyboxsdo”,这两个几何不相交。 但是当我在oralce中运行空间查询时, “从 HY90299 t,hyboxsdo g 中选择sdo_relate(t.shape,g.shape ,'mask=ANYINTERACT') ” , 我的预言机版本是11g 追加
问题内容: 我有一个循环列表,到达后我想跳过3个元素。在此答案中,提出了一些建议,但我未能充分利用它们: 四次当然是胡说八道,而四次是行不通的。 输出应如下所示: 问题答案: 用于循环;您可以在自己的代码中执行此操作,然后在循环内推进迭代器;再次调用iterable只会返回相同的iterable对象,因此您可以在下一次迭代中紧跟着在循环内推进iterable 。 通过函数推进迭代器; 它可以在Py