美文网首页
线程不安全

线程不安全

作者: 码农小钰 | 来源:发表于2020-06-24 09:57 被阅读0次

List中的ArrayList(),set中Hashset,Map中得HashMap.
当如下时主函数main为单线程操作list,list底层是一个Object得数组

public class Notsafe{
    public static void main(String[] args){
          List<String> list = new ArrayList<>();
             list.add("a");
             list.add("b");
             list.add("c");
             list.forEach(System.out::println);
    }
}

结果如下图:


image.png

模拟多线程操作list资源

public class NotSafeDemo
{
    public static void main(String[] args)
    {
        List<String> list = new ArrayList<>();

        for (int i = 1; i <=30; i++)
        {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}

则会出现如下图报错(并发修改异常)


image.png

如何解决呢?有三种方法解决上面出现得问题:
1.使用List中实现类Vector接口.这样使用Vector接口把整个list都加锁数据得一致性高度一致.

public class Test {
    public static void main(String[] args){
        List<String> list = new Vector<>();
        for (int i = 1; i <=30; i++)
        {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}

2.使用Collections工具类给list加上同步锁

3.使用写时复制(CopyOnWriteArrayList) ,推荐使用这种方法.具体代码如下,

public class NotSafeDemo
{
    public static void main(String[] args)
    {
        List<String> list = new CopyOnWriteArrayList<>();

        for (int i = 1; i <=30; i++)
        {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}
image.png

再来看看源码具体是怎么实现得
每次添加得时候复制原来得数组然后再重新定义一个新的数组,数组长度是原来长度加一,添加完之后再把旧的删除然后每次新增拿到的都是最新的数组

/**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }
image.png

set的使用,使用Hashset时如果时多线程操作则会出现并发修改异常和list一样.


image.png

解决方法一样是使用写时复制CopyOnWriteArraySet

public class NotSafeDemo
{
    public static void main(String[] args) {
        Set<String> set = new CopyOnWriteArraySet<>();
        for (int i = 1; i <=30; i++)
        {
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(set);
            },String.valueOf(i)).start();
        }
    }

Map中HashMap也是不安全得,所以三者报错得信息都是一样得,都是并发修改异常,而Map得解决方式则是使用ConcurrentHashMap线程安全的实现类.

public class NotSafeDemo
{
    public static void main(String[] args) {
        Map<String,String> map = new ConcurrentHashMap<>();
        for (int i = 1; i <=30; i++)
        {
            new Thread(()->{
                map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,8));
                System.out.println(map);
            },String.valueOf(i)).start();
        }
    }
}
image.png

相关文章

  • LocalDateTime

    SimpleDateFormat 线程不安全 SimpleDateFormat format方法是线程不安全的,源...

  • kotlin 单利模式

    1. 懒汉式 java线程不安全 缺点是在多线程不能正常工作 线程安全 效率比较低 kotlin线程不安全 线程...

  • 对 atomic 不能保证线程安全的理解

    先说说什么是线程不安全? 由多线程访问和修改共享资源造成的不可预测的结果叫做线程不安全。 如何避免线程不安全? 通...

  • iOS多线程到底不安全在哪里?

    iOS多线程到底不安全在哪里? iOS多线程到底不安全在哪里?

  • ThreadLocal可以解决并发问题吗?

    前言 到底什么是线程的不安全?为什么会存在线程的不安全?线程的不安全其实就是多个线程并发的去操作同一共享变量没用做...

  • 多线程

    科普 问题:线程不安全一定crash么? 线程不安全可能crash么?答案: 不一定 ,可能线程安全 就是多线程...

  • 单例设计模式笔记

    记录几种单例模式写法。 饿汉模式(线程不安全) 懒汉模式(线程不安全) 懒汉锁模式(线程安全) 懒汉双重判断模式(...

  • ThreadLocal解决线程安全

    线程不安全示例 SimpleDateFormat 是不安全的,被多个线程共用情况下。 使用ThreadLocal解...

  • JAVA干货|让我告诉你SimpleDateFormat线程不安

    1.什么是线程不安全? 线程不安全也叫非线程安全,是指多线程执行中,程序的执行结果和预期的结果不符的情况就叫做线程...

  • 线程安全

    线程安全 在多线程的环境下,没有表现出我们预期的行为,所以称它为线程不安全 线程不安全的例子 预期的行为?我们几个...

网友评论

      本文标题:线程不安全

      本文链接:https://www.haomeiwen.com/subject/ipglfktx.html