[英]Synchronized block still locked after thread restart
我尝试重新启动线程,但线程中的同步块在重新启动后保持锁定。 我不应该更改套接字属性,因为某些进程花费的时间太长,但是当网络连接丢失时,它会永远挂起。 我尝试使用 InterruptedException 但它不起作用。 有没有办法释放这个锁?
public static void main(String[] args) {
try {
synchronizedBlock t1 = new synchronizedBlock();
t1.start();
Thread.sleep(500);
t1.cancel();
t1 = new synchronizedBlock();
t1.start();
} catch (Exception e) {
e.printStackTrace();
}
while (true) {
}
}
public class synchronizedBlock extends Thread {
boolean isRunning = true;
boolean isRunning2 = true;
public static Object[] locks = new Object[5];
public synchronizedBlock() {
for (Integer i = 0; i < 5; i++) {
synchronizedBlock.locks[i] = i;
}
}
public void cancel() {
isRunning = false;
interrupt();
}
public void socketProces() {
while (isRunning2) {
}
}
public void proces(int index) {
try {
synchronized (locks[index]) {
System.out.println("Synchronized Block Begin");
socketProces();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
System.out.println("Run begin");
while (isRunning) {
proces(1);
}
Thread.sleep(1);
} catch (InterruptedException e) {
//Do Something
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果:
Run begin
Synchronized Block Begin
Run begin
这里的问题是Integer
缓存,它在for
循环中用于初始化synchronizedBlock.locks
数组:
for (Integer i = 0; i < 5; i++) {
synchronizedBlock.locks[i] = i;
}
当再次运行此代码时,由于第二个synchronizedBlock
的构造函数, synchronizedBlock.locks
数组包含与第一次执行此for
循环时创建的相同的Integer
实例。 这意味着synchronized (locks[index])
锁将在同一个Integer
object 上。 由于您已经有一个线程持有Integer(1)
object 的锁,因此第二个线程在lock
外等待它被释放。
结合第一个线程没有终止的事实,这也是有问题的。 你的方法
public void socketProces() {
while (isRunning2) {
}
}
是一个无限循环,因为您永远不会更改isRunning2
的值。 此外, interrupt()
方法本身不会停止任何线程。 相反,它只在Thread
class 中设置一个内部标志,可以使用isInterrupted()
和interrupted()
检查。 您必须检查此标志并对其做出反应,例如“哦,有人要我停下来,所以我现在停下来”。
要解决您的问题,您至少应该在设置Thread
实例的“isInterrupted”标志时退出您的线程。 你可以这样做:
public void socketProces() {
while (isRunning2) {
if (Thread.interrupted()) {
return;
}
}
}
您可以像其他方法一样抛出InterruptedException
,而不是从socketProces()
返回。
此外,根据您要如何初始化/使用要使用synchronized(...)
锁定的实例,您可能需要考虑如何创建/填充synchronizedBlock.locks
数组以及要使用哪些对象( Integer
缓存在这里可能有问题)。 如果创建新的synchronizedBlock
实例将/应该/不应该在synchronizedBlock.locks
数组中创建要锁定的新对象,这取决于您。
当你启动synchronizedBlock
线程时,你会得到一个我认为这样的堆栈跟踪: run
-> proces
-> socketProcess
。 然后因为isRunning2 = true
,线程会在socketProcess
中进入一个无限循环并且永远不会终止。
请记住,在 Java 中没有“重新启动” thread
之类的东西。 一旦启动,线程将永远无法重新启动。 实际上,您正在创建两个sycnchronizedBlock
对象,而不是重新启动单个 object。
作为旁注,在 class 构造函数中覆盖 static state 通常是有问题的,因为您正在使用locks
变量,没有同步。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.