龙空技术网

多线程会带来的一些问题

耀学java 109

前言:

现时你们对“多线程会产生什么问题”大约比较重视,咱们都想要知道一些“多线程会产生什么问题”的相关内容。那么小编同时在网摘上收集了一些对于“多线程会产生什么问题””的相关文章,希望各位老铁们能喜欢,咱们快快来学习一下吧!

前言

前面我们已经知道了,在使用多线程会给我们带来一些性能上的提升。但一个东西的出现总是会存在优缺点。

1、多线程会在线程安全问题

什么是线程安全?在深入理解JVM这本书中有句话可以很简单的去理解“如果一个对象可以安全地多个线程使用,那它就是线程安全的”。那么怎么去定义一个对象是可以安全的呢?个人简单的理解是:多个线程访问这个对象都能按照自己的行为执行正确的逻辑得到正确的结果。

2、JAVA内存模型

上面简单理解了一下线程安全。那么为什么会出现线程安全问题呢?其实可以先了解一下JAVA的内存模型

该图来自深入理解JVM种的一张图

主内存:主要对应于JAVA堆中的对象实例数据部分。(存在线程安全问题)

工作内存:对应于虚拟机栈中的部分区域。(线程安全的)

这就为啥在面试的时候,有些面试官会问你,在JAVA运行数据区中哪些是区域线程共享的?哪些是线程隔离的(线程私有的)?答案也很清楚:方法区和堆是线程共享的。虚拟机栈、程序计数器、本地方法栈是线程私有的。

从上面的内存模型也就知道,工作内存是线程安全的,但是主内存是线程共享的,是存在线程安全的。小Demo;

public class ThreadDemo {    static class Counter {        private int count;        public void increase() {            count++;        }        public int getCount() {            return this.count;        }    }    public static void main(String[] args) throws InterruptedException {        Counter counter = new Counter();        Thread thread1 = new Thread(new Runnable() {            @Override            public void run() {                counter.increase();            }        });        Thread thread2 = new Thread(new Runnable() {            @Override            public void run() {                counter.increase();            }        });        thread1.start();        thread2.start();        System.out.println(counter.getCount());    }}

这个小demo运行得到的结果有两种:1,2

为什么会出现这样呢?

基于内存模型将一下,为啥会出现这样的情况,因为在写操作的时候,会先从主内存中将count加载到工作内存中,但是如果出现多个线程同时去加载count,假设都是0的话,那么这个时候线程1,和线程2都是拿到count=0;然后再在自己的工作内存中进行++操作,然后再写回去到主内存,但是即使再怎么加,最终得到的结果是count=1,而不是我们想要的count=2了。

3、解决方法

其实有基础的同学,都知道解决线程安全问题的办法就是加锁。在java中会用到synchronized关键字来进行同步操作;还有一种就是使用juc包中的一些锁类。

synchronized的源码实现会在下篇文章进行解释。

总结

本章只是大致讲了一下多线程带来的利弊。

一天一个java相关小知识。喜欢的同学,可以点赞、关注+收藏,后期还会推出其他框架源码分析。

如果有需要补充的地方,留言区见。

标签: #多线程会产生什么问题