[2025.1.17 JavaSE学习]锁
synchronized机制原理
多个线程争夺锁(非公平锁)

互斥锁
基本介绍
- 每个对象都对应一个可称为“互斥锁”的标记,可以保证任意时刻,只能有一个线程访问该对象
- 同步局限性:程序执行效率降低,需要等待占有锁的线程执行完
- 同步方法(非静态)的锁可以是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来控制线程,已经过时)

浙公网安备 33010602011771号