Java多线程 - 易失性布尔不起作用?

时间:2013-01-01 01:24:09

标签: java multithreading volatile

所以我有3个线程会尝试找到一个随机生成的数字(每个线程都有自己的范围,即startNum和finishNum)。如果其中一个因为找到了数字而停止,我希望所有其他的停止同样。

我已经读过一个“volatile”布尔值,它显然是一个所有线程共享的布尔值,因此它总是1个值。

这是我的代码:(注意:如果线程结束而其他人正在进行,如果线程“停止”,因为它的startNumber超过了它的finishNumber,那就没关系了)

private volatile boolean numberFound = false;

public void run()
{
    while(startNum < finishNum) //what i'm talking about with the [note]
    {   
        search( startNum); 
        if(numberFound == true)
        {
            break;
        }       
    }   
}  
private synchronized void search(int startNum)
{
    for(int i = 0; i < 10; i++)
    {
        if( startNum != searchNum )
        {
            startNum++;
        }
        else if(startNum == searchNum )
        {
            numberFound = true;
            System.out.println( this.currentThread().getName() + " has found the number: " + searchNum );
            break;

        }

    }

}

哦,我也循环了10次,因为我希望程序在每个数字范围(线程)中检查每次10次,然后转移到另一个。

这是根据请求启动线程的main()方法:      int randomNum =(int)(Math.random()* 1001);

    FindIt t1 = new FindIt(randomNum, 0, 349); //FindIt extends Thread
    FindIt t2 = new FindIt(randomNum, 350, 699);
    FindIt t3 = new FindIt(randomNum, 700, 1000);

    t1.start();
    t2.start();
    t3.start(); 

3 个答案:

答案 0 :(得分:4)

看起来你的三个主题可能在这个类的不同实例中,因此会有3个不同的布尔值

尝试将布尔值设为静态,看看它是否会发生任何变化。

(我真的无法帮助你,因为我没有看到启动线程的代码)

注意:Volatile实际上并不意味着所有线程共享它,这意味着如果所有线程共享它,那么一个线程中的更改将反映在其他线程中的相同变量中。这是必要的,因为对于具有独立缓存的多CPU机器,一个线程可能会更新它的版本,而另一个线程可能无法获取更改,因为它已经缓存了内存....

答案 1 :(得分:1)

提及numberFound必须为static的答案是正确的。关于使用synchronized进行锁定的问题也是正确的(虽然不清楚你需要锁定这里......)。

但是另一个与并发性无关的错误导致了你的直接问题。

while(startNum < finishNum) {   
    search(startNum); 
    if(numberFound == true)
    {
        break;
    }       
}

private synchronized void search(int startNum) {
    ... 
    if (startNum != searchNum) {
        startNum++;
    }
    ...

问题是,您正在递增的startNum与您在startNum循环中测试的while不同。在Java中,参数按值传递。所以发生的事情是:

  1. 您正在将startNum方法中的run值传递给search方法。
  2. search方法将其放在局部变量中。
  3. search方法更新局部变量。
  4. 返回search方法,并启动更新后的本地变量。
  5. 返回run方法,startNum的值未发生变化。

答案 2 :(得分:0)

numberFound未声明为static,因此每个线程都将独立设置自己的属性值。 与同步方法相同 - 每个线程都会获得一个自身的锁定,所以实际上同步搜索方法可能不是你想要的。你能更好地解释为什么你这个方法同步? 这里更多关于volatile:http://www.javamex.com/tutorials/synchronization_volatile.shtml

以及有关同步和锁定的更多信息: http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

我建议有一个单独的对象,它将成为所有线程之间的共享资源 - 具有这种方法的默认锁定将在共享对象本身上执行,因此线程将开始“争夺”对象的锁定。