进程:一个程序至少要有一个进程,进程可以解释为多个线程的集合。

线程:一条可执行的操作路径。

多线程:提高效率

创建线程的4种方式1.继承Thread(其实也是实现了Runable的接口)2.实现Runable接口 3.使用匿名内部类的方式创建

4.实现Callable接口,这个是在jdk1.8之后才出现的。使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callback对象的call()方法的返回值,使用FutureTask对象作为Thread对象的target创建并启动新线程,调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。在返回值没有返回之前,主线程会阻塞。

Runable和Callable的区别Callable具有返回值,Callable声明了异常,在获得返回值的时候,主线程将会阻塞,直到子线程得到返回值或者异常结束。

线程安全:当多个线程共享一个全局变量,同时对这个全局变量进行写的操作时,造成的数据不一致的现象叫做线程安全。最好再说一下jmm内存模型。

同步代码块:可以使用任何锁,这个锁可以是一个对象,也可以是一个字符串。

同步函数:就是在方法上加上synchronized关键字,同步函数是使用的this锁,就是这个对象的锁,但是如果加上静态static关键字的话,它一开始初始化的时候就分配在了方法区里面,使用的是.class文件的锁。

多线程死锁:就是多个线程嵌套使用锁,导致互不释放彼此的锁。

守护线程:例如GC,和主线程同时消亡,主线程消亡之后,就没必要在去回收垃圾。

非守护线程(用户线程):子线程和主线程之间几乎没有任何关系,比如我们在关闭某个app的时候,后端仍会在下载,这个就是子线程。

多线程之间的几种状态:创建(也就是new),准备(start),运行(run),阻塞(wait,sleep),销毁(destory)

wait:让当前线程从运行状态变为休眠状态。

notify:让当前线程从休眠状态变为运行状态。


join:join作用是让其他线程变为等待, A.join(); // 比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。比如三个线程需要按照以下顺序执行t1,t2,t3怎么做?t2的run方法调用t1.join(),t3的run方法调用t2.join()

多线程三大特性:

1.原子性:保证线程安全问题

2.可见性:java内存模型

3.有序性volatile关键字 / java内存模型 /AtomicInteger原子类 / ThreadLock:join,wait,notify(多线程之间通讯)


我们来看看多线程的第二大特性

一:java内存模型  主要是两部分: 1.主内存(主要存放共享的全局变量)  2.私有本地内存(本地线程私有变量)

如图:t1和t2分别代表线程,

假设t1和t2不会同时操作count时,t1对count操作之后会将count刷新到主内存区的count,主内存区又会将count通知到t2的本地内存,如果始终是单线程的情况对count进行操作,那么就不会产生线程安全问题.

假设t1和t2同时会对count进行操作,同时刷新到主内存,然后通知到t1和t2线程,这时候就会出现线程安全问题.


volatile关键字 / java内存模型 /AtomicInteger原子类 / ThreadLock

说完内存模型我们再来看看volatile关键字

volatile :保证多个线程之间的可见性(强制性的将主内存,刷新到本地私有内存),但不保证原子性.

看下面的例子:如果我们不加volatile 这个关键字的话,本地内存不会刷新flag的值,加上之后会强制性的将flag的值刷新到本地内存.

另外讲一下,为什么会加上sleep,理论上来讲当我们修改主内存flag的值之后会立即刷新到本地私有内存,但是当我们sleep之后就不会立即刷新到本地内存,如果要想刷新到本地内存就需要我们手动的刷新,所以我们加上sleep的作用是为了提现volatile 关键字的作用

volatile关键字 / java内存模型 /AtomicInteger原子类 / ThreadLock

那么volatile 不能保证原子性我们应该怎么办呢?

1.加上synchronized关键字

2.AtomicInteger原子类

两者都可能达到保证原子性,但两者有本质的区别,synchronized是保证线程安全的,一个是计数用的,在jdk1.5有这样的各种类型的原子类,它的的底层原理就是CAS无锁机制。

什么是ThreadLock

为每一个线程提供一个局部变量.

这个其实很好理解,我们举一个例子,当我们创建三个线成,用的是同一个对象时,在这个对象中有一个全局共享变量,为了使每个线程都有一个属于自己变量,常规手段我们回去创建三个对象,这样三个线成使用三个不同的对象,那么有没有一种方法可以使每个线程用一个对象达到同样的效果呢,每个线程都有一个自己的变量,那么ThreadLock的效果就体现出来了.

相关文章: