java中的线程安全和非线程安全

线程安全与非安全

线程安全是指,如果代码中有多个线程同时运行,如果每一次运行的结果都是一样,或者每一次运行的结果都是跟预期一样的,或者说跟单线程运行的结果一样。那么就是线程安全。

非线程安全是指多个线程同时运行的时候,出现不确定的结果。在运行的过程中可能产生脏数据。就是线程不安全。

线程安全产生的原因

其实就是两个或多个线程同时运行的时候,共享了某个数据。在多个线程同时操作该数据的情况下,该数据没有提供加锁机制。会导致该数据在多线程操作完后是一个脏数据

例如
演示一下Stringbuilder和Stringbuffer的线程安全与不安全。
开启三条线程,每条线程同时对Stringbuffer和StringBuilder进行一千次的字符追加。那么当三条线程线程运行完毕的时候。理想结果下buffer 和 builder 的长度都应该是3000。执行结果如下

public class Demo14 {
    public static void main(String[] args) throws InterruptedException {
        StringBuffer buffer = new StringBuffer();
        StringBuilder builder = new StringBuilder();

        for (int i = 0; i < 3; i++) { //启动3条线程 同时对buffer 和 builder进行添加
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {//每条线程添加1000个字符
                    buffer.append("x");
                    builder.append("y");
                }
            }).start();
        }
        Thread.sleep(3000);
        System.out.println("buffer lenght -------->  " + buffer.length());
        System.out.println("builder lenght -------->  " + builder.length());
    }
}

第一次
在这里插入图片描述

第二次
在这里插入图片描述
显然,在builder作为三条线程的共享数据时,我们无法对builder的结果进行预测。因为Stringbuilder本身就不是一个线程安全的类。当在三个线程操作他的时候,有可能有三个线程都在同时对着某一个长度下标添加一个字符串,本应该是添加3个字符,却因为操作的是同一个下标,变成了一个。

试想一下,如果在多条线程同时操作一个线程不安全的数据集的时候,你有可能每次都获得你期望的结果吗?


再想一下,ArrayList是一个线程不安全的集合,如果把他的每个元素分别提交到一个线程里面去做处理,会有问题吗?

public class Demo15 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {

        List<String> list = Arrays.asList("云长", "翼德", "子龙", "孟起", "汉升", "孔明", "伯约", "幼常", "文长");
        ExecutorService service = Executors.newFixedThreadPool(list.size());
        for (int i = 0; i < list.size(); i++) {
            service.submit(new Mybuilder(list.get(i)));
        }
        service.shutdown();

    }
}
class Mybuilder implements Runnable {
    String name;

    public Mybuilder(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        //处理集合里面的每一个元素
        String s = Thread.currentThread().getName() + "------->" + name;
        System.out.println(s);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值