第二个线程在for循环

时间:2015-04-23 17:25:53

标签: java multithreading

这是我为研究线程而创建的测试代码。它由分配给同一个Runnable的两个线程组成。他们要扣除5成int,并停止如果int是不够大,扣除5事情是,线程1“阿尔法”不断循环,直到它半路内环路,在这种情况下是5,那么线程2“ beta“开始。这是我无法理解的一种特殊行为。我错过了什么?

public class synconizedThread implements Runnable {

    int balance = 100;

    public void run() {

        checkAmmount();
    }

    public void checkAmmount() {

        synchronized (this) {
            for (int i = 0; i < 10; i++) {

                System.out.println(Thread.currentThread().getName()
                        + "checks balance: " + balance);

                try {
                    Thread.sleep(500);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }

                withDrawAmmount();

            }
        }

    }

    public void withDrawAmmount() {

        if (balance <= 0) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }

            System.out.println("Balance is " + balance + " not enough");
        }

        else {
            balance = balance - 5;
            System.out.println(Thread.currentThread().getName()
                    + "Whitdraws, balance left:  " + balance);
        }
    }

    public static void main(String[] args) {

        Runnable myJob = new synconizedThread();

        Thread alpha = new Thread(myJob);
        alpha.setName("alpha");
        Thread beta = new Thread(myJob);
        beta.setName("beta");
        alpha.start();
        beta.start();

    }
}

5 个答案:

答案 0 :(得分:3)

您正在同步整个循环,因此第一个线程进入循环,然后在循环完成之前不会放弃CPU。

相反,您可能希望同步循环的每次迭代,这样线程就有机会交替。

您还要将呼叫同步到sleep(),这可能不是您想要做的事情。您可能希望将其移出同步之外。

public void checkAmmount() {


    for (int i = 0; i < 10; i++) {

        synchronized (this) {

            System.out.println(Thread.currentThread().getName()
                    + "checks balance: " + balance);

            withDrawAmmount();

        }

        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

}

答案 1 :(得分:3)

我看到两个问题:

  • 循环位于synchronized块内。所以无论谁得到那个锁都会先执行循环。将synchronized放在循环中。然后一个线程将在迭代结束时释放锁,并在下一个开始时再次竞争它,并且您将具有并发性。例如,制作withDrawAmount()方法synchronized。 (如果这样做,请确保将println的线程ID移至withDrawAmount()内。)
  • Thread.sleep()不释放锁定,因此不能解决循环问题在synchronized内的问题。你可能应该完全接受每个Thread.sleep()呼叫,因为它们只会减慢速度。

与以往一样,您应该尽量保持关键部分 - synchronized内的部分 - 尽可能小,以获得最大的并发性。同步withDrawAmount()应该没问题,特别是一旦你摆脱了sleep()次呼叫。如果您想获得一些乐趣并尝试查看是否可以获得更大的吞吐量,请查看java.util.conccurent.atomic.AtomicInteger

答案 2 :(得分:1)

你的第一个线程进入同步块,循环10次迭代并在每次迭代时撤回5,然后离开同步块。

因此,当完成10次迭代(并且余额为50)时,它将停止运行,离开同步块,允许第二个线程运行并执行其10次迭代。

答案 3 :(得分:1)

它是synchronized关键字。你可以在整个for循环中使用它,所以无论谁先到达它都可以运行整个for循环。

当线程A使用它时,线程B无法访问该变量 - 它被A锁定。

如果你想同时扣除两者,你应该在for循环中移动synchronized

答案 4 :(得分:0)

据我了解你的问题,你的问题是线程alpha已经在他的循环中途,直到线程beta开始。 synchronized关键字阻止所有其他线程访问同步对象。您可以将synchronized关键字放在循环中,以便每个线程进入,然后每次都离开监视器

另外,默认情况下,线程不一定得到相等的cpu时间。因此,线程alpha会在您调用start()方法后立即开始工作,并且已经过了一半,直到线程&#34; beta&#34;甚至是由主线程

启动