1、复习synchronized

案例:
1、创建资源类,提供操作数据的方法
2、创建3个售票员线程,卖出30张票

  1. class Ticket{
  2. private int ticket=30;
  3. public synchronized void saleTickets(){
  4. if(ticket>0){
  5. System.out.println(Thread.currentThread().getName()+"卖出:"+(ticket--)+"剩余:"+ticket);
  6. }
  7. }
  8. }
  9. public class SaleTicket {
  10. public static void main(String[] args) {
  11. Ticket ticket=new Ticket();
  12. new Thread(new Runnable() {
  13. @Override
  14. public void run() {
  15. for(int i=0;i<40;i++) {
  16. ticket.saleTickets();
  17. }
  18. }
  19. },"售票员1").start();
  20. new Thread(new Runnable() {
  21. @Override
  22. public void run() {
  23. for(int i=0;i<40;i++) {
  24. ticket.saleTickets();
  25. }
  26. }
  27. },"售票员2").start();
  28. new Thread(new Runnable() {
  29. @Override
  30. public void run() {
  31. for(int i=0;i<40;i++) {
  32. ticket.saleTickets();
  33. }
  34. }
  35. },"售票员3").start();
  36. }
  37. }

2、使用Lock接口改写例子

注意:使用Lock需进行异常的处理

  1. class LTicket{
  2. private int ticket=30;
  3. //创建可重入锁
  4. private final ReentrantLock lock=new ReentrantLock();
  5. public void lsaleTicket(){
  6. lock.lock();
  7. //避免在操作数据时出现异常导致锁无法释放
  8. try {
  9. if(ticket>0){
  10. System.out.println(Thread.currentThread().getName()+"卖出:"+(ticket--)+"剩余:"+ticket);
  11. }
  12. }finally {
  13. lock.unlock();
  14. }
  15. }
  16. }
  17. public class LSaleTickets {
  18. public static void main(String[] args) {
  19. LTicket ticket=new LTicket();
  20. new Thread(()->{
  21. for(int i=0;i<40;i++){
  22. ticket.lsaleTicket();
  23. }
  24. //native:start方法执行,线程不一定立刻创建,取决与硬件资源的状态
  25. },"售票员1").start();
  26. new Thread(()->{
  27. for(int i=0;i<40;i++){
  28. ticket.lsaleTicket();
  29. }
  30. },"售票员2").start();
  31. new Thread(()->{
  32. for(int i=0;i<40;i++){
  33. ticket.lsaleTicket();
  34. }
  35. },"售票员3").start();
  36. }
  37. }

3、synchronized与Lock的区别

  1. Lock 是一个接口,而 synchronized 是 Java 中的关键字,synchronized 是内置的语言实现;
    2. synchronized 在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而 Lock 在发生异常时,如果没有主动通过 unLock()去释放锁,则很可能造成死锁现象,因此使用 Lock 时需要在 finally 块中释放锁;
    3. Lock 可以让等待锁的线程响应中断,而 synchronized 却不行,使用synchronized 时,等待的线程会一直等待下去,不能够响应中断;