[2025.1.17 JavaSE学习]锁

synchronized机制原理

多个线程争夺锁(非公平锁)

image



互斥锁

基本介绍

  • 每个对象都对应一个可称为“互斥锁”的标记,可以保证任意时刻,只能有一个线程访问该对象
  • 同步局限性:程序执行效率降低,需要等待占有锁的线程执行完
  • 同步方法(非静态)的锁可以是this,也可以是其他对象
  • 同步方法(静态)的锁为当前类本身
  • 例子,使用两种方法解决售票问题:
    1、同步方法、代码块
public class Thread02{
    public static void main(String[] args){
        SellTicket s1 = new SellTicket();
        new Thread(s1).start();
        new Thread(s1).start();
        new Thread(s1).start();
    }
}

class SellTicket implements Runnable{

    private int num = 500;
    private boolean loop = true;

	//此时为一个同步方法
	//此时锁在this对象
	//也可以在代码块上同步,此时也是加在this上
    public /*synchronized*/ void m(){//方法同步
	
		synchronized (this){//代码块同步
        if(num <= 0){
            loop = false;
            return;//end
        }

        try{Thread.sleep(50);}
        catch(InterruptedException e){
            e.printStackTrace();
        }

        num --;
        System.out.println(Thread.currentThread().getName()+"Sell A Ticket");
		}
    }

    @Override
    public void run(){
        while(loop){
            m();
        }
    }
}

2、同步其他对象

public class Thread02{
    public static void main(String[] args){
        SellTicket s1 = new SellTicket();
        new Thread(s1).start();
        new Thread(s1).start();
        new Thread(s1).start();
    }
}

class SellTicket implements Runnable{

    private int num = 500;
    private boolean loop = true;
	Object object = new Object();

    public /*synchronized*/ void m(){//方法同步
	
		synchronized (object){//使用其他对象同步
        if(num <= 0){
            loop = false;
            return;//end
        }

        try{Thread.sleep(50);}
        catch(InterruptedException e){
            e.printStackTrace();
        }

        num --;
        System.out.println(Thread.currentThread().getName()+"Sell A Ticket");
		}
    }

    @Override
    public void run(){
        while(loop){
            m();
        }
    }
}

注意事项和细节

  • 同步方法如果没有static修饰,默认锁对象为this
  • 如果方法使用static修饰,默认锁对象为当前类.class
  • 实现的落地步骤
    • 先分析上锁代码
    • 选择同步代码块或同步方法
    • !!!要求多个线程的锁对象为同一个即可


死锁

基本介绍

  • 多个线程都占用了对方的资源,不肯相让,导致了死锁


释放锁

以下操作会释放锁

  • 当前线程的同步方法、代码块执行完毕
  • 当前线程在同步方法、代码块中遇到break、return
  • 当前线程在同步方法、代码块中出现了未处理的Error或者Exception,导致异常结束
  • 当前线程在同步方法、代码块中执行了线程对象的wait()方法,当前线程暂停,并释放锁

以下操作不会释放锁

  • 线程执行同步代码块或方法时,程序调用Thread.sleep()、Thread.yield()方法暂停当前线程的执行,不会释放锁
  • 线程执行同步代码块或方法时,其他线程调用了该线程的suspend()方法将该线程挂起(进入ready状态),该线程不会释放锁(尽量避免使用suspend和resume来控制线程,已经过时)
posted @ 2025-01-17 01:46  Luna-Evelyn  阅读(14)  评论(0)    收藏  举报