Skip to content

Latest commit

 

History

History
47 lines (33 loc) · 2.09 KB

File metadata and controls

47 lines (33 loc) · 2.09 KB

多线程

2 中多线程的方式:

  • 继承 Thread 类, 重写 run 方法
  • 实现 Runnable 接口, 实现 run 方法

调用 start() 方法启动线程。

线程执行步骤:

启动 ---start()--> 就绪 --获得 CPU --> 执行 ---wait()---> 阻塞 ---notify()---> 执行 ---stop()---> 死亡

  • join() 方法: 当前线程阻塞,加入的线程先执行
  • yeild() 方法: 放弃当前 CPU 执行权,让优先级高的线程先执行,当前线程仍处于 就绪 状态,仍然可以竞争 CPU
  • sleep(millis) 方法: 线程方法,当前方法进入阻塞状态,不是放同步锁, 时间到后, 继续执行。
  • wait()方法: 被锁对象方法,当前方法进入阻塞状态,释放当前同步锁, 等待 notify() 方法唤醒
  • notify()方法: 通知当前对象的阻塞资源, 进入就绪状态。

synchronized

  • 方法加 synchronized 关键字, 锁的是当前对象,并不是方法。
  • synchronized(object) {...} , 给 object 加同步锁, 锁定当前代码块。

死锁

Thread a, b; Object A, B;

Thread a 持有 B 的同步锁, 同时需要获取 A 的锁; Thread b 持有 A 的同步锁,同时需要获取 B 的锁;

Thread a 想要给 A 加锁,但发现 A 被 Thread b 已经加锁了, 所以等待 Thread b 释放 A 的锁; 同理, Thread b 想要给 B 加锁,但发现 Thread a 已经加锁了,所以也等待 Thread a 释放 B 的锁。 从而造成死锁。

  • 一个简单的死锁类
  • 当DeadLock类的对象flag==1时(td1),先锁定o1,睡眠500毫秒
  • 而td1在睡眠的时候另一个flag==0的对象(td2)线程启动,先锁定o2,睡眠500毫秒
  • td1睡眠结束后需要锁定o2才能继续执行,而此时o2已被td2锁定;
  • td2睡眠结束后需要锁定o1才能继续执行,而此时o1已被td1锁定;
  • td1、td2相互等待,都需要得到对方锁定的资源才能继续执行,从而死锁。

避免死锁:

  • 加锁顺序(线程按照一定的顺序加锁)
  • 加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)
  • 死锁检测