JAVA中Synchronized 的8种用法,绝对实用

本文详细介绍了Java中synchronized的8种使用场景,包括线程安全与不安全的案例,如同步方法、静态同步方法、同步方法调用非同步方法等。通过代码验证与分析,帮助理解synchronized关键字在多线程环境中的应用和效果。
摘要由CSDN通过智能技术生成

前言

最近针对互联网公司面试问到的知识点,总结出了Java程序员面试涉及到的绝大部分面试题及答案分享给大家,希望能帮助到你面试前的复习且找到一个好的工作,也节省你在网上搜索资料的时间来学习。

内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、MySQL、Spring、SpringBoot、SpringCloud、RabbitMQ、Kafka、Linux等技术栈。

完整版Java面试题地址:JAVA后端面试题整合

八种使用场景:

接下来,我们来通过代码实现,分别判断以下场景是不是线程安全的,以及原因是什么。

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)共同竞争一把类锁,就可以使两个线程串行执行了。这也就是下一个场景要讲的内容。

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

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

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

场景四:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值