一般而言,在现在的项目开发大多都是以框架为基础而搭建,关于线程关于锁的使用更多的体现是在分布式与锁之中,但是基本的只是原理还是需要了解。我们需要了解以下:
1-------什么是多线程,多线程的场景,多线程的实现;
2-------什么是锁,在什么时候需要锁,怎么使用锁;
======================================多线程================================================
进程:一个程序就是一个进程,windows系统的运行可以看成一个进程!
线程:进程中的分支,一个进程是一个程序运行的主干,那么在这其中发生的其他直线就是线程!
多线程是指一个进程产生了多个分支(线程)
场景:
并行:多个线程同一时间操作了相同的资源,多条道路,同一时间点,底层部分先后地到达
并发:在单位时刻内,同时有多个线程操作同一个资源,如果按照用户来计算,那么在底层仍然存在着顺序
线程安全:线程安全是为了保证在开发过程中,多个线程的调用,先后顺序变化,最后不会影响到任何一个线程的结果!
线程状态:
1-----初始状态,创建了Thread对象但是并没有调用start()方法
2-----就绪状态,对象创建后,调用了start(),就差获取CPU试用权,或则调用yield()直接昂起当前获取到的CPU使用权
2-----运行状态,线程中将获取到CPU的使用权,运行running()时的状态称为“运行”
3-----阻塞状态,线程因为一些原因放弃CPU的使用权,直接进入就绪状态(阻塞分为三种)
-------同步阻塞:因为获取锁被占用而阻塞
-------等待阻塞:该线程执行了wait()方法,释放掉自身的锁,本身是不能被自启动的,只能等待notify()或者notifyAll()来唤醒
-------其他阻塞:线程启动了sleep()或者被join()或者发起了IO请求,那么线程会等待到处理完成后再次进入就绪状态;这个过程中sleep()或者join()不在拥有CPU的使用权,但是并不释放锁。sleep和join结束后直接进入运行状态
4-----死亡状态:退出run()方法
=========================================================================================
常用基础:synchronized, wait, notify 是任何对象都具有的同步工具
注意:synchronized的使用其本质都是去雇佣一个对象或者实例来作为管理者,管理者会执行阻塞,等待与唤醒的功能,因此在使用synchronized的时候需要明确管理者是谁。wait()和notify()和notifyAll()需要在synchronized中才可以使用!
非静态,对公共资源加加锁1:
public class Thread1 implements Runnable { Object lock; //可以是任意对象,但必须存在,且唯一 public void run() { synchronized(lock){ //在run方法中加锁的,相当于代码块被添加了锁 ..do something } } } |
非静态,对公共资源加锁2:
public class Thread1 implements Runnable { public synchronized void run() { //直接加载在run方法上的锁,默认该类对象为给管理者 ..do something } } |
注意:synchronized(this)以及非static的synchronized方法,只能防止多个线程同时执行同一个对象的同步代码段。synchronied(this)锁住的是括号里面的对象!因此如果在执行过程中如果synchronized所在的对象也被重新创建了,那么是允许多个线程一起执行的!这样锁是阻止不了的
此外:因为涉及到对象的使用,如果可以在代码段上使用锁则不要在方法上加锁,为了减少线程的访问时间
那么如果我一定要再多个对象呗创建也要锁住这段代码呢,那么可以寻找一个固定的对象来锁住,比如该对象的Class,一般在生产上常用于这种方法,在方法内部锁住代码块:synchronized (XXX.class) XXX为携带锁的类名,类似于全局锁的作用
静态:
static synchronized 方法 也相当于全局锁 |
静态情况下,因为静态是属于类变量,可以不添加,默认使用了该代码的 Class类!
==========================================================================================
voliate:共享变量以及禁止指令重排序
在系统的操作中,如果涉及到写入数据的操作速度会比较慢,为了提高效率,一般都是先从主内存中复制一份数据到高速缓存中,线程对缓存处理后,再修改写入主存中。那么当多个线程同时操作的时候,那么我们需要加锁,那么读取但线程读取的时候我们则可能造成脏数据,因此在读取的我们需要强制读取到当前最新的数据,该关键字保障了数据的可见性!
在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性!因此voliate会阻止指令集的改变,保障多线程结果的正确性!