文章目录
1.线程和进程
- Java线程:Thread,Runnable,Callable
1.线程状态
- NEW
- RUNNABLE
- BLOCKED
- WATING
- TIMED_WAITING
- TERMINATED
2.wait和sleep区别
- 父类:
wait->Object
sleep->Thread - 锁的释放:wait会释放锁,sleep不会释放锁
- 异常:wait不需要异常,sleep需要捕获异常
- 适用范围:wait必须在同步代码块,sleep无限制
2.Lock锁
1.Synchronized和Lock区别
- Synchronized是内置Java关键字,Lock是Java类
- Synchronized无法判断获取锁的状态,Lock可判断
- Synchronized会自动释放锁,Lock必须手动
- Synchronized线程1获得锁,线程2等待。Lock锁就不会等待
- Synchronized可重入锁,不可中断,非公平。Lock可重入,可判断锁,非公平
- Synchronized适合少量的代码同步问题,Lock适合锁大量代码
锁精析
static方法调用方式是通过class.fun,而非static方法调用是先new出这个对象,再调用。
static synchronized是类锁,synchronized是对象锁。
类锁(又称全局锁,static synchronized):该锁针对的是类,无论实例出多少个对象,那么线程依然共享该锁。
static synchronized是限制多线程中该类所有添加staic修饰的方法,即该类中用static修饰的方法是同步的。(实例.fun实际上相当于class.fun)
对象锁(又称实例锁,synchronized):该锁针对的是该实例对象(当前对象)。
synchronized是对类的当前实例(当前对象)进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块,注意这里是“类的当前实例”, 类的两个不同实例就没有这种约束了。
每个对象都有一个锁,且是唯一的。
- 两个线程,用同一个对象调用两个加锁的方法a和b,其中a延时四秒执行
此时锁上给的是调用方法的对象,因为两个方法用的同一个对象,所以执行顺序a,b - 两个线程,用同一个对象调用一个加锁一个不加锁的方法a和b,其中a延时四秒执行
此时b方法不是同步的,所以执行顺序b,a - 两个线程,用两个对象调用两个加锁的方法a和b,其中a延时四秒执行
此时锁上给的是调用方法的对象,因为两个方法用的不同对象,所以执行顺序b,a - 两个线程,用两个对象调用两个加锁的静态方法a和b,其中a延时四秒执行
此时锁上给的是类对象,因为两个方法用的同一个类生成的不同对象,所以执行顺序a,b - 两个线程,用一个对象调用两个加锁的静态方法a和非静态方法b,其中a延时四秒执行
此时锁上给的是类对象,因为两个方法用的同一个类生成的不同对象,所以执行顺序a,b
ReadWriteLock
- 概念:**写入(独占锁)**可线程同时读取;**读锁(共享锁)**只能一个线程写。
- 创建方式:
ReadWriteLock readWriteLock= new ReentrantReadWriteLock() ;
- 使用方式:
写入的方法在方法体头中加入readWriteLock.writeLock().lock();
方法体尾加入readWriteLock.writeLock().unlock();
只读的方法在方法体头中加入readWriteLock.readLock().lock();
方法体尾加入readWriteLock.readLock().unlock();
2.并发下ArrayList和ArraySet不安全
解决方案
- List < String> list=new Vector<>();
- List < String> list=Collections.synchronizedList(new ArrayList<>());
- CopyOnWriteArrayList/ CopyOnWriteArraySet写时复制
向一个容器添加元素时先将此容器复制,然后向复制后的容器添加元素,这样原容器不需要加任何锁,可以实现同步读操作,然后添加完元素后将引用指向新的copy触的容器。也就是所说的读写分离机制。可解决高并发下的线程安全问题
3.Callable
Callable接口类似于Runnable ,因为它们都是为其实例可能由另一个线程执行的类设计的
4.辅助类
CountDownLatch减法计数器
- 调用.countDown()方法,数量减一
- .await()方法:等待计数器归零,然后执行后面的
CyclicBarrier加法计数器
大概的意思就是一个可循环利用的屏障。
所有线程会等待全部线程到达栅栏之后才会继续执行
可以用于多线程计算数据,最后合并计算结果的场景
- CyclicBarrier 与 CountDownLatch 区别