在多个线程之间共享和更新变量而不在java中同步

时间:2017-06-20 06:29:41

标签: java multithreading

我正在尝试使用多线程模拟java中100米的跑步比赛程序。在这次尝试中,我创建了一个原子整数变量,该变量应该对所有线程都是通用的。每个线程越过100后,此变量应增加1.不幸的是结果不如预期。这是我对该程序的尝试。

    package running;
    import java.util.concurrent.atomic.*;
    public class Employee implements Runnable{
    AtomicInteger j = new AtomicInteger();

public void run() {

for(int i=1;i<=100;i++){
        System.out.println(Thread.currentThread().getName()+" " + i);
        try {
             Thread.sleep(100);
        } 
        catch (InterruptedException e) {
             e.printStackTrace();
        }
        if(i==100)
        {
             System.out.println(Thread.currentThread().getName()+" is in "+j.incrementAndGet()+" place");

        }
}
} 

public static void main(String []args) throws Exception{
Employee e= new Employee();
Thread a= new Thread(e,"First");
Thread b= new Thread(e,"Second");
Thread c= new Thread(e,"Third");
Thread d= new Thread(e,"Fourth");
Thread f= new Thread(e,"Fifth");
a.start();
b.start();
c.start();
d.start();
f.start();

}
}

为了以可理解的方式演示我的问题,我添加了一个print语句来检查代码中线程的运行情况。这是输出的最后10行。

Second 100
Fourth 100
Third 100
Fifth 100
First 100
Fourth is in 3 place
Third is in 1 place
Second is in 2 place
Fifth is in 4 place
First is in 5 place

1 个答案:

答案 0 :(得分:1)

我没有看到意想不到的结果。当我运行你的代码时,我得到:

First is in 1 place
Third is in 3 place
Second is in 4 place
Fifth is in 2 place
Fourth is in 5 place

如果我再次运行代码,我明白了:

First is in 1 place
Second is in 2 place
Fifth is in 4 place
Fourth is in 3 place
Third is in 5 place

如预期的那样,结果并不总是一样的。并且AtomicInteger没有丢失任何更新。

如果希望按顺序显示结果,则需要同步注册结果的代码部分。 (以确保达到100的第一个线程将在下一个线程达到100之前写入该信息),例如,见下文:

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicInteger;

public class Employee implements Runnable {
    private static AtomicInteger j = new AtomicInteger();
    private static Queue<String> queue = new ArrayDeque<>();

    public static void main(String[] args) throws Exception {
        Employee e = new Employee();
        Thread a = new Thread(e, "First");
        Thread b = new Thread(e, "Second");
        Thread c = new Thread(e, "Third");
        Thread d = new Thread(e, "Fourth");
        Thread f = new Thread(e, "Fifth");
        a.start();
        b.start();
        c.start();
        d.start();
        f.start();

        a.join();
        b.join();
        c.join();
        d.join();
        f.join();

        while (queue.size() > 0) {
            System.out.println(queue.remove());
        }

    }

    public void run() {

        for (int i = 1; i <= 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (queue) {
                if (i == 100) {
                    queue.add(Thread.currentThread().getName() + " is in " + j.incrementAndGet() + " place");
                }
            }
        }
    }
}