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");
    
    
        }
    }
  • 相关阅读:
    ObjectiveC初步研究 实现文件(Implementation File)
    SQL技巧(二) CTE(公用表达式)初步接触
    ObjectiveC编程基础
    Linux编程 使用C在mysql中插入数据
    办理户口
    修改kernel内核HZ频率没有效果问题
    如何从湖北省人才市场将户口迁移出来?
    查看 各种寄存器值的 内核模块 C语言
    SDRAM AND SRAM
    linux2.6.26内核中ARM中断实现详解(转)
  • 原文地址:https://www.cnblogs.com/Tony100/p/12922458.html
Copyright © 2011-2022 走看看