Java 多线程同步块永远循环
Java Multi Threading synchronized block Looping forever
我实现了示例程序以确保一次执行特定进程的线程不超过 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() 方法中的计数变量以获取最新值。但它总是返回值 5。
请让我知道哪里出错了。
当您在 class 中同步静态方法时,这意味着两者都锁定在同一监视器上,即 class 本身。
所以当Thread-5
进入while循环时,会无限持有锁,而线程1-4还在等待获取锁进入decrementCounter
。
您的代码存在的主要问题如下:
在Java中,在同一个class中,只有一个Thread可以在static synchronized方法中执行。 [Reference]
- 这意味着您的线程将在开始时暂停
MiscUtils.incrementCounter
的执行。
- 它也将阻止
MiscUtils.decrementCounter
的执行。
count
达到5后,thread-5
会卡在循环里while(MiscUtils.getCount() > 4)
- 那么
thread-5
之后的所有线程都将启动,但会进入休眠状态,因为同步静态方法 MiscUtils.incrementCounter
仍然卡在 thread-5
.
这样肯定会死循环
我希望这是一个明确的答案。
我实现了示例程序以确保一次执行特定进程的线程不超过 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() 方法中的计数变量以获取最新值。但它总是返回值 5。 请让我知道哪里出错了。
当您在 class 中同步静态方法时,这意味着两者都锁定在同一监视器上,即 class 本身。
所以当Thread-5
进入while循环时,会无限持有锁,而线程1-4还在等待获取锁进入decrementCounter
。
您的代码存在的主要问题如下:
在Java中,在同一个class中,只有一个Thread可以在static synchronized方法中执行。 [Reference]
- 这意味着您的线程将在开始时暂停
MiscUtils.incrementCounter
的执行。 - 它也将阻止
MiscUtils.decrementCounter
的执行。 count
达到5后,thread-5
会卡在循环里while(MiscUtils.getCount() > 4)
- 那么
thread-5
之后的所有线程都将启动,但会进入休眠状态,因为同步静态方法MiscUtils.incrementCounter
仍然卡在thread-5
.
这样肯定会死循环
我希望这是一个明确的答案。