synchronized 的用法

本文详细分析了synchronized在不同场景下的应用,包括同步方法的访问,如线程访问同一对象或不同对象的同步方法,静态与非静态同步方法,以及异常处理。通过案例解释了何时线程安全,何时线程不安全,帮助理解synchronized的锁机制。
摘要由CSDN通过智能技术生成

        同步方法的访问场景,多线程访问同步方法是否还是线程安全的。这些场景是多线程编程中经常遇到的,而且也是面试时高频被问到的问题,所以不管是理论还是实践,这些都是多线程场景必须要掌握的场景。

1.synchronized  同步方法的访问场景

  1. 两个线程同时访问同一个对象的同步方法

  2. 两个线程同时访问两个对象的同步方法

  3. 两个线程同时访问(一个或两个)对象的静态同步方法

  4. 两个线程分别同时访问(一个或两个)对象的同步方法和非同步方法

  5. 两个线程访问同一个对象中的同步方法,同步方法又调用一个非同步方法

  6. 两个线程同时访问同一个对象的不同的同步方法

  7. 两个线程分别同时访问静态synchronized和非静态synchronized方法

  8. 同步方法抛出异常后,JVM会自动释放锁的情况

场景一:两个线程同时访问同一个对象的同步方法

        分析:这种情况是经典的对象锁中的方法锁,两个线程争夺同一个对象锁,所以会相互等待,是线程安全的。

        结论:两个线程同时访问同一个对象的同步方法,是线程安全的。

场景二:两个线程同时访问两个对象的同步方法

        这种场景就是对象锁失效的场景,原因出在访问的是两个对象的同步方法,那么这两个线程分别持有的两个线程的锁,所以是互相不会受限的。加锁的目的是为了让多个线程竞争同一把锁,而这种情况多个线程之间不再竞争同一把锁,而是分别持有一把锁,

        结论:两个线程同时访问两个对象的同步方法,是线程不安全的。

public class Condition2 implements Runnable {  
    // 创建两个不同的对象  
 static Condition2 instance1 = new Condition2();  
 static Condition2 instance2 = new Condition2();  
  
 @Override  
 public void run() {  
  method();  
 }  
  
 private synchronized void method() {  
  System.out.println("线程名:" + Thread.currentThread().getName() + ",运行开始");  
  try {  
   Thread.sleep(4000);  
  } catch (InterruptedException e) {  
   e.printStackTrace();  
  }  
  System.out.println("线程:" + Thread.currentThread().getName() + ",运行结束");  
 }  
  
 public static void main(String[] args) {  
  Thread thread1 = new Thread(instance1);  
  Thread thread2 = new Thread(instance2);  
  thread1.start();  
  thread2.start();  
  while (thread1.isAlive() || thread2.isAlive()) {  
  }  
  System.out.println("测试结束");  
 }  
}  
线程名:Thread-0,运行开始  
线程名:Thread-1,运行开始  
线程:Thread-0,运行结束  
线程:Thread-1,运行结束  
测试结束 

代码分析:

        两个线程(thread1、thread2),访问两个对象(instance1、instance2)的同步方法(method()),两个线程都有各自的锁,不能形成两个线程竞争一把锁的局势,所以这时,synchronized修饰的方法method()和不用synchronized修饰的效果一样(不信去把synchronized关键字去掉,运行结果一样),所以此时的method()只是个普通方法。

问题解决:

        若要使锁生效,只需将method()方法用static修饰,这样就形成了类锁,多个实例(instance1、instance2)共同竞争一把类锁,就可以使两个线程串行执行了。这也就是下一个场景要讲的内容。

场景三:两个线程同时访问(一个或两个)对象的静态同步方法

这个场景解决的是场景二中出现的线程不安全问题,即用类锁实现:

两个线程同时访问(一个或两个)对象的静态同步方法,是线程安全的。

场景四:两个线程分别同时访问(一个或两个)对象的同步方法和非同步方法

        这个场景是两个线程其中一个访问同步方法,另一个访问非同步方法,此时程序会不会串行执行呢,也就是说是不是线程安全的呢?
        我们可以确定是线程不安全的,如果方法不加synchronized都是安全的,那就不需要同步方法了。

        结论:两个线程分别同时访问(一个或两个)对

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值