java 线程中断 io 操作_JDK问题:中断在IO操作上被阻塞的另一个线程,信号可能会失败...

OpenJDK实现(linux部分)使用信号来中断在本机IO操作上阻塞的另一个线程 . 基本思想是,向目标线程发送唤醒信号将导致阻塞IO调用返回EINTR .

例如,在异步关闭使用的fd时中断被阻塞的线程:

static int closefd(int fd1, int fd2) {

...

/*

* Send a wakeup signal to all threads blocked on this

* file descriptor.

*/

threadEntry_t *curr = fdEntry->threads;

while (curr != NULL) {

curr->intr = 1;

pthread_kill( curr->thr, sigWakeup );

curr = curr->next;

}

...

}

另一个例子是中断套接字通道:

protected void implCloseSelectableChannel() throws IOException {

...

// Signal native threads, if needed. If a target thread is not

// currently blocked in an I/O operation then no harm is done since

// the signal handler doesn't actually do anything.

//

if (readerThread != 0)

NativeThread.signal(readerThread);

if (writerThread != 0)

NativeThread.signal(writerThread);

...

}

但是,可能存在阻塞线程将错过信号并且不会被中断的竞赛 .

为了演示,我写了一小段测试代码:

#include

#include

#include

void handler(int sig) {

printf("singal\n");

}

int main() {

// set-up an interrupting signal handler

signal(SIGINT, handler);

// not blocking operation, prepare to block

// if the wake-up signal arrived during this

// operation. we'll miss it.

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

int j = i * i;

}

printf("not blocking operation done\n");

// blocking io operation

unsigned int remain = sleep(10);

printf("blocking io operation done, remain %u\n", remain);

return 0;

}

如果唤醒信号在被阻塞的线程进入内核之前到达以等待IO,例如执行一些glibc的包装代码,则被阻塞的线程将永远错过该信号并且未被中断 .

信号在IO之前到达时的输出如下:

./a.out

^Csingal

^Csingal

^Csingal

^Csingal

^Csingal

not blocking operation done

blocking io operation done, remain 0

当IO阻塞后信号到达时的输出:

./a.out

not blocking operation done

^Csingal

blocking io operation done, remain 6

这是一个JDK错误还是我错过了什么?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值