回顾:
我们到web阶段的程序都是多线程,web下的项目都是多线程环境
会创建一个.class类,同时开辟多个线程,同时使用,由web服务器自动做
Thread有四个方法:
两个成员方法:getName(),获取线程名称
setName()设置线程名称
两个静态方法:
currentThread()获取当前线程对象
sleep()让当前线程暂停指定的毫秒值
多线程的运行原理:
两个线程一起工作,两个线程会无序运行,
常见的高并发的线程安全性问题:
变量的可见性:一个线程的访问频率太快,他如果访问速度太快,会从方法区加载到自己的main栈方法单独做一个副本,不会再去方法区找变量,会导致,方法区内的变量更改,此线程也没变化.
代码的有序性:代码重排的问题,一段代码,JVM编译器再编译的时候,为了提高效率,在不影响执行结果的情况下,可能会对代码进行重排,在多线程的环境下,就会出现问题,导致结果不一样.
变量访问的原子性: 多个线程共同访问同一变量,由于访问的代码不具有原子性(不可再拆分的),说一导致最终结果不准确.
原子性:在java中,对基本数据类型的变量和赋值操作都是原子性操作
j=i;是两个操作,读取i,将i赋值给j
i++;是三个操作,读取i值,i+1;将+1的结果赋值给i
在单线程环境中,我们可以认为整个步骤都是原子性操作,但在多线程环境下,Java
只保证了基本数据类型的变量和赋值操作才是原子性(在32位的jdk环境下,对64位数据的操作不是原子性操作,如long,double)
https://blog.csdn.net/u013412772/article/details/80109727
cas机制,乐观锁会先取这个值,交给cas的一个方法,告诉他我要把这个值变成另外的一个值
所以cas方法做这个事,先比较,会从内存中先把值取出来,去跟你要改的值进行比较,如果一样,执行修改,不一样就自旋,再取一次,再去比较,乐观锁,
对数组进行操作的原子类,AtomicIntegerArray,int类型数据进行原子操作
AtomicLongArray,对Long[]数据进行原子操作
AtomicReferenceArray,对引用类型数组原子操作
在多线程环境下,这三个问题要全部解决,才是一个好的解决方案,第三方的线程框架,这些框架提出的解决方案,java类库提出的解决方案就是原子类
web项目默认多线程环境
,需要了解的:线程安全
正式学习:
synchronized(同步)关键字:对一段代码
作用:我们对一段代码或者一个方法整体的进行多线程安全的控制,它代表同步的,可以保证单个线程在执行这段代码时,其他的线程不能执行这段代码,要排队等待
使用方式:
同步代码块:
同步方法(常用)
同步代码块:需要同一个共享的锁对象,需要静态的,普通对象,不共享.
使用结构:继承Thread类,重写run()方法,在run方法内写synchronized(共享的对象,需要时static修饰的){
代码块
}
一个线程抢到锁了之后,释放锁的时候,还继续参与抢锁
synchronized可以锁run放在重写run方法的void之前,自定义MyThread对象实现Runable接口,并且在测试类中,new一个自定义对象,再使用自定义对象来作为Thread的有参方法,再使用Thread的start方法
同步方法:将一个方法整体设置为同步的,使用synchronized关键字
格式:
自定义类继承Thread类,方法为public static synchronized 返回值类型 方法名(形参列表){ }
static的原因是:普通成员方法的锁对象是:本对象
静态方法的锁对象是本类的Class对象,JVM会为每一个类创建一个class对象,加上静态的关键字
测试时,需要new多个自定义类,给自定义类setname(""),再start()
实现Runnable接口的synichronized关键字的使用方式
Thread.currentThread().getName(),获取当前的线程对象的线程名
自定义类实现Runnable接口,方法可以不使用static关键字修饰,,测试类中只需要new一个自定义类,再通过new Thread(自定义类名)的有参构造方法来创建多个线程
也可以synchronized修饰run方法,
synchronized被称为悲观锁:无论是否有线程安全,都会加锁,就会有额外的操作,就会降低效率
CAS机制,被称为"乐观锁",比较并交换,"比较"的大部分时候都是线程安全的.针对少数发生线程安全问题时,才采用"自旋",再JDK1.5之后的JUC包(java.util.concurrent包)中的很多原子类,同步类,都是使用CAS机制实现,比较快
Lock锁:提供了一种新的锁:java.util.concurrent.Lock(接口),使用方法的形式进行枷锁,释放锁,比synchronized更加灵活,
Lock锁的内部tong'bu'dia'a'm
CopyOnWriteArrayList类(线程安全的)
CopyOnWriteArraySet类
ConcurrentHashMap类
多线程控制的工具类:
CountDownLatch多线程协作
CyclicBarrier多线程协作
Semaphore并发数量控制
Exchanger线程信息交互
synchronized,我们相对一段代码或者一个方法进行多线程安全的控制,
她表示同步的,可以保证一个线程在使用这端代码或者这个方法是,其他线程不能执行这段代码
要排队等待
使用方式:同步代码块 同步方法(常用)
同步代码块:方法(){
synchronized(锁对象){
}
}
他必须是一个对象,任何对象都可以,但必须保证多个线程共享同一个锁对象
普通成员方法:锁对象是本对象
静态方法=>锁对象:本类的class对象