线程安全问题是什么?要如何解决?

TheDisguiser 2020-05-26 21:14:55 java常见问答 5267

有时候在进程中会遇到线程安全问题,这会让人很头疼,你知道线程为什么会出现安全问题吗?又该如何解决呢?小编整理了一些相关内容,快来学习一下吧。

一、为什么会出现线程安全问题?

以计算机来说,在计算机系统中,系统资源分配的单位被称为进程,而在同一个进程计算机允许多个线程并发执行,并且多个线程能够共享进程范围内的资源,如内存地址等。但是,当多个线程当多个线程并发访问同一个内存地址并且内存地址保存的值是可变的时候就有可能会发生线程安全问题,因此需要内存数据共享机制来保证线程安全问题。

例:

public class ThreadUnsafeDemo
{
    private static final ExecutorService EXECUTOR_SERVICE;
    static
    {
        EXECUTOR_SERVICE = new ThreadPoolExecutor(100, 100, 1000 * 10
            , TimeUnit.SECONDS, new LinkedBlockingQueue(100), new ThreadFactory()
            {
                private AtomicLong atomicLong = new AtomicLong(1);
                @Override
                public Thread newThread(Runnable r)
                {
                    return new Thread(r, "Thread-Safe-Thread-" +
                        atomicLong.getAndIncrement());
                }
            });
    }
    public static void main(String[] args) throws Exception
    {
        Mapparams = new HashMap < > ();
        ListfutureList = new ArrayList < > (100);
        for (int i = 0; i < 100; i++)
        {
            futureList.add(EXECUTOR_SERVICE.submit(new CacheOpTask(params)));
        }
        for (Future future: futureList)
        {
            System.out.println("Future result:" + future.get());
        }
        System.out.println(params);
    }
    private static class CacheOpTask implements Callable
    {
        private Mapparams;
        CacheOpTask(Mapparams)
        {
            this.params = params;
        }
        @Override
        public Integer call()
        {
            for (int i = 0; i < 100; i++)
            {
                int count = params.getOrDefault("count", 0);
                params.put("count", ++count);
            }
            return params.get("count");
        }
    }
}
创建100个task, 每个task对map中的元素累加100此, 程序执行结果为:
{
    count = 9846
}
而预期的正确结果为:
{
    count = 10000
}

其中,判断是否有线程安全性的一个原则是:是否有多线程访问可变的共享变量。

二、如何解决线程的安全问题?

两种方法:

1、成为不可变类,不可变类就是指,在这个类中,一旦它的对象被创建出来,在其整个生命周期中,它的成员变量就不能被修改、

2、使用synchronized关键字,这个关键字就是为了使这个类变成线程安全的。

一般来说,能避免并发安全问题方式就是它们了,它们分别为不变性和隔离性,synchronized就是为了实现隔离性,以使并行的访问变为线性的访问。

如果一个可变类没有一个synchronized关键字,它就肯定不是线程安全的,带有synchronized关键字的可能是线程安全的类型,Hashtable中的好多方法带有synchronized,所以它是线程安全的。

synchronize关键字就是为了解决线程安全问题而诞生的。

以上就是本文的所有内容了,线程安全问题其实只要注意代码规范是很容易避免的,如果你还想了解更多与之相关java常见问答知识,就快快关注我们的网站吧。

推荐阅读:

线程安全的类在java中有几种?如何成为线程安全类?

java线程安全的map有哪几种?为什么是线程安全的呢?

线程安全与线程不安全如何来理解呢?