分布式调度 Wendy 微信商家收款 Flutter security datagridview null chartjs vue前端框架 git视频教程 jquery循环遍历 bentley软件介绍 hadoop创建文件夹 mysql卸载工具 jquery validate python正则提取字符串 python日期转时间戳 java中的多态 java时间函数 java中tostring java文档 java正则表达式详解 java获取ip地址 java接口实例 java数组排序 rendercontrol 右键菜单背景 灼热峡谷 梦幻西游手游助手 通达信金融终端官网 qq免安装版 linux运维之道 什么软件买电影票便宜 tableau下载 保留小数点后两位 珊瑚版 lol不能全屏 寂静城 苹果手机耳机没声音 失心迷宫怎么打
当前位置: 首页 > 学习教程  > 编程语言

synchronized学习记录

2020/8/31 15:32:55 文章标签:

跳转仙女棒

  • 一、概念
  • 二、对象锁和类锁
  • 三、根据使用对象和使用方法分类
    • 根据修饰对象分类
    • 根据获取的锁分类
  • 四、总结
  • 五、测试代码
    • 测试类锁
    • 测试对象锁

一、概念

synchronized 是 Java 中的关键字,是利用锁的机制来实现同步的。

锁机制有如下两种特性:

  • 互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制,这样在同一时间只有一个线程对需同步的代码块(复合操作)进行访问。互斥性我们也往往称为操作的原子性。

  • 可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的(即在获得锁时应获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作从而引起不一致。

二、对象锁和类锁

  • 对象锁 在 Java 中,每个对象都会有一个 monitor 对象,这个对象其实就是 Java
    对象的锁,通常会被称为“内置锁”或“对象锁”。类的对象可以有多个,所以每个对象有其独立的对象锁,互不干扰。
  • 类锁
    在 Java 中,针对每个类也有一个锁,可以称为“类锁”,类锁实际上是通过对象锁实现的,即类的 Class 对象锁。每个类只有一个 Class 对象,所以每个类只有一个类锁。
    synchronized 的用法可以从两个维度上面分类:

三、根据使用对象和使用方法分类

根据修饰对象分类

synchronized 可以修饰方法和代码块

修饰代码块

  • synchronized(this|object) {}
  • synchronized(类.class) {}

修饰方法

  • 修饰非静态方法
  • 修饰静态方法

根据获取的锁分类

获取对象锁

  • synchronized(this|object) {}
  • 修饰非静态方法

获取类锁

  • synchronized(类.class) {}
  • 修饰静态方法,非静态方法

四、总结

  • 对于静态方法采用类锁;
  • 对于非静态方法,同一个实例的线程访问会被拦截,非同一实例可以同时访问。 即此时是默认对象锁(this)。
  • 只要采用类锁,就会拦截所有线程,只能让一个线程访问。
  • 对于对象锁(this),如果是同一个实例,就会按顺序访问,但是如果是不同实例,就可以同时访问。
  • 如果对象锁跟访问的对象没有关系,那么就会都同时访问。

五、测试代码

测试类锁

public class testMain {
    private  static  int count;

    public static void main(String[] args) {

        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(10);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    //每个线程让count自增100次
                    for (int i = 0; i < 100; i++) {
                        synchronized (this.getClass()){
                            count++;
                        }
                    }
                }
            }).start();
        }

        try{
            Thread.sleep(2000);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(count);
    }
}

此处用this.getclass()为类锁,显示结果200
使用this为对象锁,显示结果小于等于200随机数

测试对象锁

import org.jetbrains.annotations.NotNull;

public class testMain2 {
    private  static  int count;

    public static void main(String[] args) {
        Runnable target = getTarget();

        for (int i = 0; i < 2; i++) {
            new Thread(target).start();
        }

        try{
            Thread.sleep(2000);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(count);
    }

    @NotNull
    private static Runnable getTarget() {
        return new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(10);
                } catch ( Exception e ) {
                    e.printStackTrace();
                }
                //每个线程让count自增100次
                for (int i = 0; i < 100; i++) {
                    synchronized (this) {
                        count++;
                    }
                }
            }
        };
    }
}

此处无论是否使用this.getClass 还是 this 均返回200,对象锁生效

文章参考博客园 huansky synchronized(this) 与synchronized(class) 之间的区别


本文链接: http://www.dtmao.cc/news_show_150348.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?