linux多线程随机数,随机数SecureRandom在Linux下阻塞

问题背景

在项目中,需要使用随机数,直接使用new Random()效率太低,为了提高随机性和性能,sonar建议,使用子类java.security.SecureRandom来实现。

问题程序public class Test {

public static void main(String[] args) throws java.security.NoSuchAlgorithmException {

byte[] k = new byte[20];

java.security.SecureRandom.getInstanceStrong().nextBytes(k);

System.out.println(java.util.Arrays.toString(k));

}

}

此代码在本地环境(Win10 + OracleJDK8)和测试环境(CentOS7 + OpenJDK1.8)均能正常输出结果。但是在云服务器(CentOS7 + OpenJDK1.8)一直阻塞。

问题解析

通过查询资料,发现SecureRandom.getInstanceStrong()方法在Linux环境下使用/dev/random生成随机数的种子。但是/dev/random是一个阻塞数字生成器,如果没有足够的随机数据,那么就会一直等待,迫使 JVM 阻塞。

Linux内核采用熵来描述数据的随机性,熵(entropy)是描述系统混乱无序程度的物理量,一个系统的熵越大则说明该系统的有序性越差,即不确定性越大。内核维护了一个熵池用来收集来自设备驱动程序和其它来源的环境噪音。

简言之就是键盘和鼠标的输入以及磁盘活动可以产生所需的随机性或熵。

但在一个缺乏这样的活动服务器,可能会出现问题,当系统的熵池中数量不足时,就会阻塞当前线程。

Linux的随机数

random设备了提供了2个字符设备供用户态进程使用:/dev/random适用于对随机数质量要求比较高的请求,在熵池中数据不足时, 读取/dev/random设备时会返回小于熵池噪声总数的随机字节。/dev/random可生成高随机性的公钥或一次性密码本。若熵池空了,对/dev/random的读操作将会被阻塞,直到收集到了足够的环境噪声为止。这样的设计使得/dev/random是真正的随机数发生器,提供了最大可能的随机数据熵。

/dev/urandom非阻塞的随机数发生器,它会重复使用熵池中的数据以产生伪随机数据。这表示对/dev/urandom的读取操作不会产生阻塞,但其输出的熵可能小于/dev/random的。它可以作为生成较低强度密码的伪随机数生成器,对大多数应用来说,随机性是可以接受的。

解决方案

使用/dev/urandom非阻塞的方式来产生随机数,用new SecureRandom()代替SecureRandom.getInstanceStrong()。public class Test {

public static void main(String[] args) {

byte[] k = new byte[20];

new java.security.SecureRandom().nextBytes(k);

System.out.println(java.util.Arrays.toString(k));

}

}

注:以上代码片段直接使用命令行编译运行javac Test.java

java Test

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值