1、并发
并发:同一个对象被多个线程同时操作
2、线程同步
处理多线程问题时,多个线程访问同一个对象,又可能会出错,所以我们需要让这些线程排对等候,一个一个访问这些对象。线程同步就是一种等待机制,多个需要访问这个对象的线程进入这个对象的等待池 形成队列,等前面的线程使用完毕,下一个线程在使用。
3、队列和锁
遇到的问题:
1、一个线程持有了这个对象的锁,会使其他所有需要此锁的线程挂起。
2、在多线程竞争下,拿锁,释放锁会导致较多的上下文切换和调度时延,引起性能问题
3、如果一个优先级高的线程等待一个优先级低的线程释放锁,那么会引起优先级倒置,引起性能问题
4、三大线程不安全案例(没有给对象加锁)
这里介绍给对象加锁的2种方法:
1、在方法前加synchronized关键字的同步方法,锁的是this;---------同步方法
2、synchronized(需要锁的对象){代码块}-----------同步代码块方法
3、Lock锁方式下面单独介绍
1、不安全的买票,多个买票线程操作一个对象(票)--------同步方法、同步代码块方法
如果我门不加锁,直接写方法void buy(){},没有在方法前面加synchronized关键字,就没有给对象this加锁,所以当在操作this的nums票数时就会发生错误。
//不安全的买票
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
new Thread(buyTicket,"易恒").start();
new Thread(buyTicket,"易馨").start();
new Thread(buyTicket,"周润发").start();
}
}
class BuyTicket implements Runnable{
//总票数
private int nums=10;
boolean flag=true;
@Override
public void run() {
//买票
while (flag){
try {
//让三个线程在这里都等1秒钟,以免cpu性能太高每次循环都让第一个线程先跑。
Thread.sleep(1000);
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//synchronized同步方法,锁的是this
synchronized void buy() throws InterruptedException {
// synchronized (this){
if(nums<=0){
flag=false;
return;
}else {
System.out.println(Thread.currentThread().getName()+"抢到了第"+nums--+"张票");
}
}
// }
}
2、不安全的取钱:卡里面一共有100万,你取50万,你妻子取90万。假如两者同时发生,会发生线程不安全。--------同步代码块方法
这里我使用了同步代码块synchronized (account){},account这个对象就是在多线程访问中需要改变的对象,所以我们需要给account加一把锁,访问这个对象的线程都会排好队,当一个线程在访问对象时,这个线程会拿到对象的排它锁,等访问完毕就释放这个锁,下一个线程接着访问。
//不安全的取钱
//卡里面一共有100万,你取50万,你妻子取90万>假如两者同时发生,会发生线程不安全。
public class UnsafeBank {
public static void