栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【多线程锁】synchronized对象锁与类锁用法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【多线程锁】synchronized对象锁与类锁用法

文章目录
    • 一、概念
        • 1. 概念
        • 2. 特性
      • 二、用法分类
        • 1. 按照修饰对象
        • 2. 按照获取的锁分类
      • 三、代码实战
        • 1. 锁住实体中的非静态变量(对象锁)
        • 2. 锁住实体中的静态变量(类锁)
        • 3. 锁住无关对象
        • 4. 锁住this对象(对象锁)
        • 5. 锁住类对象(类锁)
        • 6. 锁住非静态方法(对象锁)
        • 7. 锁住静态方法(类锁)
      • 四、总结

一、概念 1. 概念

​ synchronized是java中的关键字,可以在需要线程安全的业务场景中进行使用,保证线程安全,它是利用锁机制来实现同步的。

2. 特性
  • 原子性:同一时间只允许一个线程持有某个对象锁,对需同步的代码块(复合操作)进行访问,是一种排他的机制,因此被synchronized关键字修饰的同步代码块是无法被中途打断的,能保证代码的原子性

  • 可见性:synchronized关键字包括monitor enter和monitor exit两个JVM命令,它能保证在任何时候任何线程执行到monitor enter成功之前都必须从主内存中获取数据,而不是从缓存中,在monitor exit运行成功之后,共享变量被更新后的值必须刷入主内存。

  • 有序性:synchronized的指令严格遵守java happens-before规则,一个monitor exit指令之前必定要有一个monitor enter;这种顺序性是以程序的串行化执行换来的,在synchronized关键字所修饰的代码块中代码指令也会发生指令重排序的情况

二、用法分类 1. 按照修饰对象
  • 修饰代码块
    • synchronized(this|object) {}
    • synchronized(类.class) {}
  • 修饰方法
    • 修饰非静态方法
    • 修饰静态方法
2. 按照获取的锁分类
  • 获取对象锁
    • synchronized(this|object) {}
    • 修饰非静态方法
  • 获取类锁
    • synchronized(类.class) {}
    • 修饰静态方法
  • 对象锁与类锁的区别
    • 对象锁:每个实例都会有一个monitor对象,即Java对象的锁,类的对象可以有多个,所以每个对象有其独立的对象锁,互不干扰
    • 类锁:每个类只有一个Class对象,所以每个类只有一个类锁;类锁是加载类上的,而类信息是存在JVM方法区的,并且整个JVM只有一份,方法区又是所有线程共享的,所以类锁是所有线程共享的
三、代码实战 1. 锁住实体中的非静态变量(对象锁)
@Slf4j
public class SyncThread implements Runnable {

    private final Object lock = new Object();

    @Override
    public void run() {
        syncMethod();
    }

    private void syncMethod() {
        log.info("thread in");
        synchronized (lock) {
            try {
                log.info("thread start");
                TimeUnit.SECONDS.sleep(2);
                log.info("thread end");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

测试代码

public class SyncTest {

    public static void main(String[] args) {
        SyncThread syncThread = new SyncThread();
        new Thread(new SyncThread(), "thread-1").start();
        new Thread(new SyncThread(), "thread-2").start();
        new Thread(syncThread, "thread-3").start();
        new Thread(syncThread, "thread-4").start();
    }
}

运行结果

结论:如果是同一个实例,就会按顺序访问,如果是不同实例,就可以同时访问

2. 锁住实体中的静态变量(类锁)
@Slf4j
public class SyncThread implements Runnable {

    private static final Object lock = new Object();

    @Override
    public void run() {
        syncMethod();
    }

    private void syncMethod() {
        log.info("thread in");
        synchronized (lock) {
            try {
                log.info("thread start");
                TimeUnit.SECONDS.sleep(2);
                log.info("thread end");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果

结论:所有实例按照顺序访问

3. 锁住无关对象
@Slf4j
public class SyncThread implements Runnable {

    @Override
    public void run() {
        syncMethod();
    }

    private void syncMethod() {
        log.info("thread in");
        synchronized (new SyncThread()) {
            try {
                log.info("thread start");
                TimeUnit.SECONDS.sleep(2);
                log.info("thread end");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果

结论:所有实例同时访问

4. 锁住this对象(对象锁)
@Slf4j
public class SyncThread implements Runnable {

    @Override
    public void run() {
        syncMethod();
    }

    private void syncMethod() {
        log.info("thread in");
        synchronized (this) {
            try {
                log.info("thread start");
                TimeUnit.SECONDS.sleep(2);
                log.info("thread end");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果

结论:如果是同一个实例,就会按顺序访问,如果是不同实例,就可以同时访问

5. 锁住类对象(类锁)
@Slf4j
public class SyncThread implements Runnable {

    @Override
    public void run() {
        syncMethod();
    }

    private void syncMethod() {
        log.info("thread in");
        synchronized (SyncThread.class) {
            try {
                log.info("thread start");
                TimeUnit.SECONDS.sleep(2);
                log.info("thread end");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

执行结果

结论:所有实例按照顺序访问

6. 锁住非静态方法(对象锁)
@Slf4j
public class SyncThread implements Runnable {

    @Override
    public void run() {
        syncMethod();
    }

    private synchronized void syncMethod() {
        log.info("thread in");
        try {
            log.info("thread start");
            TimeUnit.SECONDS.sleep(2);
            log.info("thread end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果

结论:如果是同一个实例,就会按顺序访问,如果是不同实例,就可以同时访问

7. 锁住静态方法(类锁)
@Slf4j
public class SyncThread implements Runnable {

    @Override
    public void run() {
        syncMethod();
    }

    private synchronized static void syncMethod() {
        log.info("thread in");
        try {
            log.info("thread start");
            TimeUnit.SECONDS.sleep(2);
            log.info("thread end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果

结论:所有实例按照顺序访问

四、总结

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1013372.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号