Java多线程同步块永远循环

问题描述 投票:0回答:2

我实施了示例程序,以确保一次执行一个特定进程的线程不超过5个。但是结果却不如预期。

public class MiscUtils{

    private volatile static int count = 0;


    public synchronized static int getCount() {
        return count;
    }

    public synchronized static boolean incrementCounter() throws InterruptedException {
        System.out.println("count - " + count);
        while(MiscUtils.getCount() > 4) {
            System.out.println(Thread.currentThread().getName() + " Sleeping..");
            Thread.sleep(1000 * 5);
        }
        System.out.println("Thread acquired " + Thread.currentThread().getName());
        if(count > 4) {
            return false;
        }
        count++;
        return true;
    }

    public synchronized static boolean decrementCounter() {
        System.out.println("Decrement Called " + Thread.currentThread().getName());
        count--;
        return true;
    }


    public static void main(String[] args) throws InterruptedException {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                try {
                    //System.out.println(new Date() + " :: Thread incremented");
                    MiscUtils.incrementCounter();
                    Thread.sleep(10 * 1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                MiscUtils.decrementCounter();
                System.out.println(Thread.currentThread().getName());
            }

        };
        int count = 10;
        for(int i = 0; i < count; i++) {
            Thread s = new Thread(r);
            System.out.println(new Date() + "Thread " + i + " starting..");
            s.start();
            System.out.println(new Date() + "Thread " + i + " started..");
            Thread.sleep(1 * 1000);
        }

    }
}

实际输出:

Mon Dec 30 19:29:20 IST 2019Thread 0 starting..
Mon Dec 30 19:29:20 IST 2019Thread 0 started..
count - 0
Thread acquired Thread-0
Mon Dec 30 19:29:21 IST 2019Thread 1 starting..
Mon Dec 30 19:29:21 IST 2019Thread 1 started..
count - 1
Thread acquired Thread-1
Mon Dec 30 19:29:22 IST 2019Thread 2 starting..
Mon Dec 30 19:29:22 IST 2019Thread 2 started..
count - 2
Thread acquired Thread-2
Mon Dec 30 19:29:23 IST 2019Thread 3 starting..
Mon Dec 30 19:29:23 IST 2019Thread 3 started..
count - 3
Thread acquired Thread-3
Mon Dec 30 19:29:24 IST 2019Thread 4 starting..
Mon Dec 30 19:29:24 IST 2019Thread 4 started..
count - 4
Thread acquired Thread-4
Mon Dec 30 19:29:25 IST 2019Thread 5 starting..
Mon Dec 30 19:29:25 IST 2019Thread 5 started..
count - 5
Thread-5 Sleeping..
Mon Dec 30 19:29:26 IST 2019Thread 6 starting..
Mon Dec 30 19:29:26 IST 2019Thread 6 started..
Mon Dec 30 19:29:27 IST 2019Thread 7 starting..
Mon Dec 30 19:29:27 IST 2019Thread 7 started..
Mon Dec 30 19:29:28 IST 2019Thread 8 starting..
Mon Dec 30 19:29:28 IST 2019Thread 8 started..
Mon Dec 30 19:29:29 IST 2019Thread 9 starting..
Mon Dec 30 19:29:29 IST 2019Thread 9 started..
Thread-5 Sleeping..
Thread-5 Sleeping..
Thread-5 Sleeping..
Thread-5 Sleeping..
Thread-5 Sleeping..
Thread-5 Sleeping..
Thread-5 Sleeping..

预期输出-

Mon Dec 30 19:29:20 IST 2019Thread 0 starting..
Mon Dec 30 19:29:20 IST 2019Thread 0 started..
count - 0
Thread acquired Thread-0
Mon Dec 30 19:29:21 IST 2019Thread 1 starting..
Mon Dec 30 19:29:21 IST 2019Thread 1 started..
count - 1
Thread acquired Thread-1
Mon Dec 30 19:29:22 IST 2019Thread 2 starting..
Mon Dec 30 19:29:22 IST 2019Thread 2 started..
count - 2
Thread acquired Thread-2
Mon Dec 30 19:29:23 IST 2019Thread 3 starting..
Mon Dec 30 19:29:23 IST 2019Thread 3 started..
count - 3
Thread acquired Thread-3
Mon Dec 30 19:29:24 IST 2019Thread 4 starting..
Mon Dec 30 19:29:24 IST 2019Thread 4 started..
count - 4
Thread acquired Thread-4
Mon Dec 30 19:29:25 IST 2019Thread 5 starting..
Mon Dec 30 19:29:25 IST 2019Thread 5 started..
count - 5
Thread-5 Sleeping..
Mon Dec 30 19:29:26 IST 2019Thread 6 starting..
Mon Dec 30 19:29:26 IST 2019Thread 6 started..
Mon Dec 30 19:29:27 IST 2019Thread 7 starting..
Mon Dec 30 19:29:27 IST 2019Thread 7 started..
Mon Dec 30 19:29:28 IST 2019Thread 8 starting..
Mon Dec 30 19:29:28 IST 2019Thread 8 started..
Mon Dec 30 19:29:29 IST 2019Thread 9 starting..
Mon Dec 30 19:29:29 IST 2019Thread 9 started..
Thread-5 Sleeping..
Thread-5 Sleeping..
Thread acquired Thread-5
Thread-6 Sleeping..
Thread acquired Thread-6
and so on...

DecrementCounter()方法永远不会被调用。另外,我希望同步块应该更新getCount()方法中的count变量以获取最新值。但是它总是返回值5。请让我知道我哪里出了问题。

java multithreading thread-safety thread-synchronization
2个回答
3
投票

当您在类中同步了静态方法时,这意味着它们都锁定在作为类本身的同一监视器上。

因此,当Thread-5进入while循环时,它将在线程1-4仍在等待获取进入decrementCounter的锁的同时无限期地持有该锁。


0
投票

您的代码的主要问题如下:

在Java中,只有一个线程可以在同一类的静态同步方法内执行。 [Reference]

  • 这意味着您的线程将在开始时保留MiscUtils.incrementCounter的执行。
  • 也将阻止MiscUtils.decrementCounter的执行。
  • count达到5后,thread-5将卡在循环while(MiscUtils.getCount() > 4)
  • 然后,thread-5之后的所有线程将被启动,但将进入睡眠状态,因为同步静态方法MiscUtils.incrementCounter仍然被thread-5阻塞。

这肯定会导致无限循环。

我希望这是一个明确的答案。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.