使用线程增加int

时间:2016-05-22 05:14:21

标签: java multithreading

我有两个线程,我希望在小于某个值时增加一个int变量。我的程序执行此操作但两个不同的线程不会单独增加值 如果onetwo是两个线程,我希望输出像这样

one 1  
two 2  
one 3  
two 4  
one 5  
two 6  
one 7  
two 8...  

这是我的计划:

class IncTo100Demo implements Runnable {
    public volatile int count = 0;

    public void run() {
        Thread current = Thread.currentThread();
        try {
            while(count < 21) {
                System.out.println(current.getName() + " count = " + count++);
                current.sleep(1000);
            }
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Thread one = new Thread(new IncTo100Demo(), "one");
        Thread two = new Thread(new IncTo100Demo(), "two");

        try {
            one.start();
            two.start();
            System.out.println("one alive? " + one.isAlive());
            one.join();
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}  

,其输出为:

one alive? true
two count = 0
one count = 0
two count = 1
one count = 1
two count = 2
one count = 2
two count = 3
one count = 3
two count = 4
one count = 4
two count = 5
one count = 5
two count = 6
one count = 6
two count = 7
one count = 7
two count = 8
one count = 8
two count = 9  

如何让这些线程单独更新变量,以便输出看起来像我想要的那样?

2 个答案:

答案 0 :(得分:6)

count是类IncTo100Demo的实例变量。每个线程都使用自己的该类实例,因此可以使用自己的该变量副本。这就是他们独立更新价值的原因。要使线程共享,您必须让它们使用相同的类实例,或者必须使count静态。

此外,一旦两个线程访问相同的count变量,使该变量为volatile不足以保证您想要的行为。您可能可能看到该行为,但仍有可能一个线程无法看到该变量的其他更新。这是因为评估表达式count++并应用其副作用不是原子的。因此,两个线程都可以读取count的相同值(即,在任何一个写入更新值之前)。在这种情况下,两者都将计算相同的更新值,并且两者都将编写它。结果看起来与您提供的错误输出相似,但可能(非常)偶然,不一致。

为了避免这个问题,您需要同步对count的访问权限(后者也不需要是易失性的)。您不能通过同步run()方法来实现这一点,但是,这会使方法使用调用run()的对象的监视器进行同步。如果你的线程使用相同的IncTo100Demo实例,那么这将阻止任何并发,如果它们没有,那么那将是无效的。

而是使用run()内的同步块。如果两个线程共享相同的IncTo100Demo实例(我建议),那么您可以在该实例上进行同步:

synchronized (this) {
    // ... read and manipulate 'count'
}

否则,您需要创建在线程之间共享的另一个对象,并在其上进行同步。请注意,每次循环迭代中对count的所有访问都在同一个同步块内(包括count < 21测试),但sleep()在它之外。您希望同步范围尽可能窄。

由于这似乎是一项教育活动,我会留下详细信息供您解决,但我会给您提示:您可能需要重新构建循环。

答案 1 :(得分:-1)

static 关键字添加 count 变量的声明