繁体   English   中英

线程重启后同步块仍然锁定

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM