zoukankan      html  css  js  c++  java
  • synchronized

    
    

    synchronized的使用方式有两种

      1 对一个对象进行加锁

      

    synchronized(O){
        //代码
    }

      2 对一个方法加锁

    public synchornized void func(){
        //代码
    }

    其实无论是对一个对象进行加锁还是对一个方法进行加锁,实际上,都是对对象进行加锁

    java中一个对象由三部分组成=>

    1 对象头=>markwork(hashCode(只有在调用后才会有),GC分代年龄,锁信息),class指针,如果是数组的话还会有一个数组的长度

    2 实例数据=》存放对象字段的数据

    3 填充数据=》为了保证一个对象所占用的字节数是8的倍数,提高执行效率

    4 如果对象是数组的话对象头

     偏向锁的概念一直不太好理解,偏向锁其实没有上锁,只是将线程指针加到对象头中,在更改的时候原理是cas。之所要偏向锁,是因为大部分情况下都是一个进程在操作,当有竞争的时候,需要将锁升级(一般升级为轻量级锁,如果加了await就直接进入重量级锁,在升为轻量级锁的时候,偏向的线程也要和其他的线程重新进行cas操作来获取锁),但是在升级的时候会让偏向的这个线程先获取锁,偏向锁的意义就是为了让偏向的线程先获取锁。

    偏向锁产生的条件?=》只有偏向锁已启动(即偏向锁的标志位为1)的对象才能产生偏向锁,如果没有则直接进入轻量级锁。

    对象如何启动偏向?=》只有在jvm启动一段时间(一般4秒钟)后创建的对象jvm才会给该对象头的偏向锁标志位设置为1。

    代码示例:

        public static void main(String[] args)  {
    
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(() -> {
    
                Object o = new Object();
                synchronized (o){
                    System.out.println(ClassLayout.parseInstance(o).toPrintable());
                }
            }).start();
    }

     偏向锁是否一定比自旋锁效率高?

      不一定,在明确知道会有多线程竞争的情况下,偏向锁肯定会涉及锁撤销,这时候直接使用自旋锁。

    可见性:

    JMM关于synchronized的两条规定:

    1)在线程执行的代码中遇到释放锁前,必须把工作内存中共享变量的最新值刷新到主内存中

    2)在线程执行的代码中中遇到获得锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新获取最新的值

    public class Test
    {
        private static int x = 0;
        private static int y = 0;
    
        public static void main(String[] args) {
    
            new Thread(() -> {
                while (true) {
                    synchronized (Test.class) {
                    }
                    if (x == 1 & y == 2) {
                        System.out.println("thread1 end");
                        break;
                    }
                }
    
            }).start();
    
            new Thread(() -> {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                x = 1;
                y = 2;
            }).start();
    
            System.out.println("main is end");
    
    
        }
    }
  • 相关阅读:
    LintCode Python 简单级题目 488.快乐数
    LintCode Python 简单级题目 100.删除排序数组中的重复数字 101.删除排序数组中的重复数字II
    LintCode Python 简单级题目 373.奇偶分割数组
    LintCode Python 简单级题目 39.恢复旋转排序数组
    LintCode Python 简单级题目 35.翻转链表
    LintCode Python 简单级题目 451.两两交换链表中的节点
    LintCode Python 简单级题目 174.删除链表中倒数第n个节点
    aws查看官方centos镜像imageid
    linux shell脚本查找重复行/查找非重复行/去除重复行/重复行统计
    php配置优化-生产环境应用版
  • 原文地址:https://www.cnblogs.com/Tony100/p/12922458.html
Copyright © 2011-2022 走看看