多线程的目的

为什么要使用多线程?可以简单的分两个方面来说:

  • 在多个cpu核心下,多线程的好处是显而易见的,不然多个cpu核心只跑一个线程其他的核心就都浪费了;

  • 即便不考虑多核心,在单核下,多线程也是有意义的,因为在一些操作,比如IO操作阻塞的时候,是不需要cpu参与的,这时候cpu就可以另开一个线程去做别的事情,等待IO操作完成再回到之前的线程继续执行即可。

多线程带来的问题

其实多线程根本的问题只有一个:线程间变量的共享

java里的变量可以分3类:

  1. 类变量(类里面static修饰的变量)

  2. 实例变量(类里面的普通变量)

  3. 局部变量(方法里声明的变量)

下图是jvm的内存区域划分图:

seo优化培训,网络推广培训,网络营销培训,SEM培训,网络优化,在线营销培训

根据各个区域的定义,我们可以知道:

  1. 类变量 保存在“方法区”

  2. 实例变量 保存在“堆”

  3. 局部变量 保存在 “虚拟机栈”

“方法区”和“堆”都属于线程共享数据区,“虚拟机栈”属于线程私有数据区。

因此,局部变量是不能多个线程共享的,而类变量和实例变量是可以多个线程共享的。事实上,在java中,多线程间进行通信的唯一途径就是通过类变量和实例变量。

也就是说,如果一段多线程程序中如果没有类变量和实例变量,那么这段多线程程序就一定是线程安全的。

以Web开发的Servlet为例,一般我们开发的时候,自己的类继承HttpServlet之后,重写doPost()、doGet()处理请求,不管我们在这两个方法里写什么代码,只要没有操作类变量或实例变量,最后写出来的代码就是线程安全的。如果在Servlet类里面加了实例变量,就很可能出现线程安全性问题,解决方法就是把实例变量改为ThreadLocal变量,而ThreadLocal实现的含义就是让实例变量变成了“线程私有”的,即给每一个线程分配一个自己的值。

 

 现在我们知道:其实多线程根本的问题只有一个:线程间变量的共享,这里的变量,指的就是类变量和实例变量,后续的一切,都是为了解决类变量和实例变量共享的安全问题。

如何安全的共享变量

现在唯一的问题就是要让多个线程安全的共享变量(下文中的变量一般特指类变量和实例变量),上文提到了一种ThreadLocal的方式,其实这种方式并不是真正的共享,而是为每个线程分配一个自己的值。

网友评论