[锁] synchronized与ReentrantLock

前言

关于锁,这两个锁应该是面试最常见的内容;

ReentrantLock原理

深入理解Java并发之synchronized实现原理

上面两个大佬的文章,应该是看来看去写得比较清晰明白的了。

在回顾完这两个锁的实现,我又有一些新的疑问。

疑问

1.ReentrantLock的Node.SIGNAL这是什么东西,几种状态有什么意义

2.CAS面试要掌握到什么程度呢?

3.线程的中断?线程有哪些状态?

4.AQS和cas

5.操作系统线程是怎么切换的,内核态,用户态?

6.底层的操作系统的Mutex Lock?

7.i++操作细节,和++i的区别

另外需要回顾:

并发编程内存屏障

JUC的源码之前看的,现在得拾到拾到。

下面先从简单的,逐步突破:

问题解决

1.i++操作细节,和++i的区别

for循环中为什么用 ++i 比 i++ 更好 ?

结论:是否先入栈再自增,还是先自增再入栈。

++i,是先自增再赋值,i++是先赋值再自增(从字面上讲,也是能理解的,这样就会多一个临时变量)。

i++ 要在内存中多创建一个临时变量,多执行一步占用内存更高。

前面是i++ 后面是++i

i++ 要多创建一个临时变量,所以在一样语义的时候,用i++比较好。

i++在字节码文件是这样的:

看大佬的解析锁的那部分,我就直接截取这边的i++

public class SyncCodeBlock {

   public int i;

   public void syncTask(){
       //同步代码库
       synchronized (this){
           i++;
       }
   }
}

         4: aload_0
         5: dup
         6: getfield      #2             // Field i:I
         9: iconst_1
        10: iadd
        11: putfield      #2            // Field i:I
        14: aload_1

我查阅了一下大概是这样的: 

 aload_0 从局部变量0中装载引用类型值

dup 复制栈顶部一个字长内容

 getfield 从对象中获取字段

iconst_1 将int类型常量1压入栈

 iadd 执行int类型的加法

putfield 设置对象中字段的值

aload_1 从局部变量1中装载引用类型值

关于:

int i = 1;

i = ++i + i++;

System.out.println(i);

结果是4

         0: iconst_1  //将常量数字1入栈
         1: istore_1 //出栈赋值给局部变量表i=1
         2: iinc          1, 1 // 局部变量表i,自增加1 等于2
         5: iload_1 // 2入栈
         6: iload_1 //2再次入栈
         7: iinc          1, 1 // 局部变量表i自增1,等于3
        10: iadd // 操作数栈中的2+2相加等于4
        11: istore_1 //出栈,替换局部变量表i的3为4。
————————————————
版权声明:本文为CSDN博主「可乐多点冰」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013541707/article/details/112513620

int i = 1;
// 1 + 3 + 3 + 5
i = i++ + ++i + i++ + ++i;
System.out.println(i);

/**
 * 0: iconst_1 数值1入栈
 * 1: istore_1 数值1出栈赋值给i
 * 2: iload_1 i(1)入操作数栈
 * 3: iinc          1, 1 i在局部变量表自增1,此时i=2
 * 6: iinc          1, 1 i在局部变量表自增1,此时i=3
 * 9: iload_1 i继续入栈,第二次为3
 * 10: iadd 相加,与第一次栈中1和第二次的3相加为4,此时栈中为只有一个值且4
 * 11: iload_1 又把局部变量表中的i=3入栈
 * 12: iinc          1, 1  局部变量表中i为3自增1,变为了4
 * 15: iadd 4+3等于7
 * 16: iinc          1, 1 局部变量表中i为4自增1,变为了5
 * 19: iload_1 i=5入操作数栈
 * 20: iadd 与原本操作数栈中的7相加,等于12
 * 21: istore_1 出栈返回给局部变量表中的i,即此时i从5变为了12
 **/

结果是:12

以上就是i++和++i的底层分析,终极区别是,是否先入栈再自增,还是先自增再入栈。

https://blog.csdn.net/u013541707/article/details/112513620 这个作者讲的好好~

2. CAS面试需要什么程度?

CAS:Compare and Swap,比较并交换。CAS有3个操作数:内存值V、预期值A、要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。该操作是一个原子操作,被广泛的应用在Java的底层实现中。在Java CAS主要是由sun.misc.Unsafe这个类通过JNI调用CPU底层指令实现

3. [线程]java的线程状态以及如何新建线程

 [线程]java的线程状态以及如何新建线程 : https://blog.csdn.net/pmdream/article/details/119868141

[线程]线程池的使用和7个参数的含义:https://blog.csdn.net/pmdream/article/details/119873615

4. [线程]操作系统线程是怎么切换的(用户态的内部切换)

https://blog.csdn.net/pmdream/article/details/119881080

5.[volitate]volatile和synchronized特点

https://blog.csdn.net/pmdream/article/details/107821238

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值