一. 回顾学习内容
在前面几篇博客中我我们已经理解了 synchronized 对象锁, 对象锁的重入, synchronized 方法块, synchronized 非本对象的代码块,
链接: https://www.cnblogs.com/SAM-CJM/category/1314992.html
我们来总结一下, 上面几篇讲到内容:
1. 创建线程类的两个方式: 继承 Thread 类和实现 Runable 接口.
2. 了解了 Thread 类的几个基本构造器.
3. 启动多线程时要使用 start 方法, 不要直接调用 run 方法.
4. 几个多线程中常用的方法.
5. 解决一个共享资源被多个线程调用时采用了 synchronized 同步化一个对象的方法.
6. 一个线程可以在进入一个同步化的方法时再去进入这个对象的另外一个同步化方法, 这个就是对象锁的重入.
7. 为了提高程序的执行效率, 我们可以不去直接同步一个方法, 直接同步这个方法中有关共享数据的部分, 其他部分就是异步执行的.
8. 上一篇讲到了使用 synchronized 同步一个不是本对象的代码块
二. 导入问题
我们到现在使用的 synchronized 方法同步的都是非静态的方法也就是给一个对象上来一把对象锁, 那么我们去给一个静态方法会有什么效果呢?
三. 同步将静态方法, 同步类资源
其实在 Java 中给一个静态方法上锁就是给一个类上锁, 因为类也可以是一个共享资源.
代码如下:
- public class SynClass {// 这个类为共享资源
- // 这个静态方法没有被同步
- public static void fun() throws InterruptedException {
- System.out.println("**************begin**************");
- Thread.sleep(4000);
- System.out.println("**************end**************");
- }
- public static void main(String[] args) {
- ThreadA t1=new ThreadA();
- ThreadA t2=new ThreadA();
- t1.start();
- t2.start();
- }
- }
- class ThreadA extends Thread {// 创建线程
- @Override
- public void run(){
- try {
- SynClass.fun();// 调用静态方法
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
结果就是出现了线程不同步:
修改代码如下:
- // 这个静态方法被同步
- synchronized public static void fun() throws InterruptedException {
- System.out.println("**************begin**************");
- Thread.sleep(4000);
- System.out.println("**************end**************");
- }
结果被同步:
说明类也可以是共享资源, 同步静态方法也是在同步类资源.
四. 类锁和对象锁的认识
假如我们有两把锁一把是类锁, 一把是对象锁, 那么会出现什么情况呢?
代码如下:
- public class SynClassObject {
- // 创建一个同步的静态的方法
- public synchronized static void static_fun(){// 类锁
- System.out.println("********** 静态方法 begin*********");
- System.out.println("********** 静态方法 end***********");
- }
- // 创建同步的非静态方法
- public synchronized void notStatic_fun(){// 对象锁
- System.out.println("*********** 非静态方法 begin*************");
- System.out.println("*********** 非静态方法 end***************");
- }
- public static void main(String[] args) {
- new SynClassObjectThread1().start();
- new SynClassObjectThread2().start();
- }
- }
- class SynClassObjectThread1 extends Thread{// 这个线程类调用的是同步化的静态方法
- @Override
- public void run(){
- SynClassObject.static_fun();
- }
- }
- class SynClassObjectThread2 extends Thread{// 这个线程类是调用非静态方法
- private SynClassObject synClassObject =new SynClassObject();
- @Override
- public void run(){
- synClassObject.notStatic_fun();
- }
- }
结果入下:
明显他是不同步的, 因为对象锁和类锁是两把不同的锁.
同样的道理对于同步静态代码块, 也是对类资源实现了一个同步.
来源: https://www.cnblogs.com/SAM-CJM/p/9810820.html