并发编程学习笔记2

多线程锁的os内核理解

os同步的方式

  • 1.互斥量(mutex)
  • 2.自旋锁(spinlock)
  • 3.信号量

sysnchronized

1.关键字实现在interpreterRuntime.cpp中的moniterenter

2.synchronizer.cpp

  • 底层使用的不是自旋锁
  • jvm内部获取锁的时候也没有自旋

3.锁膨胀

mutex

操作系统级别同步原语

man pthread_mutex_init

  • 初始化和销毁一个互斥量(一把锁)

  • 引入pthread.h头文件

  • mutextest.c

    • sharei = 0;

      mutex = PTHREAD_MUTEX_INITIALIZER(调用了上面man后面的方法)

    • pthread_t t1,t2,t3

      int ret;

      ret = pthread_create($t1,null,increase_num(void),null)

    • incease_num(void)

      {

      ​ pthead_mutex_lock(&mutex)

      ​ tmp = sharei;

      ​ tmp = tmp +1;

      ​ share = tmp;

      ​ pthread_mutex_unlock(&mutex)

      }

  • synchronized底层用的就是mutex,是一把互斥锁,是一把重量级锁,不是自旋锁

  • 1.mutex实现的锁是互斥锁,java当中对于synchronized关键字如果是重量锁(数字10),它底层同步或者锁机制用的是mutex;如果不是10,与对象头相关,所以也可能是轻量锁。

    2.什么时候变成重量级锁,是因为锁膨胀,是可逆的,当一个线程持有锁,当另一个也来获取锁时,此时锁会膨胀,变为重量级锁。

    3.线上很多代码,很多时候没有并发,所有直接用synchronized是性能很差的,此时只是偏向锁,也就是说高并发情况下才会变成重量级锁,所以高并发情况下,尽量避免用锁,通过mq、copyonwrite、解决,对于超卖这种特殊情况则需要使用synchronized,

    4.mutex为什么是重量锁?mutex互斥特点是拿不到锁就会sleep,调用sleep()会进入内核态,sleep是一种内核操作,因为发生了一次系统调用,jdk1.6之间是重量级锁,所以睡眠线程进入了内核态,当线程唤醒,它被唤醒,又从内核态切换为用户态。ReentrantLock中没有调用sleep,只用了cas,而cas不是内核操作,所以ReentrantLock是轻量级锁。

    5.什么是内核态?线程的本质 ->jvm ->内核线程(一对一模型)

    5a. 优点:jvm不需要做什么操作,通过各种native方法区实现了线程

    5b.缺点 由于线程的底层需要内核线程来实现,所以java多线程切换时,需要频繁切换内核态和用户态,造成资源浪费

    6.内核态?用户态?跟线程无关,跟cpu有关,需要看当前cpu是什么状态,执行自己的代码是用户态,执行系统代码,需要进行系统的内核升级,此时就变成了内核态,

    6.a mmu mmap,虚拟地址映射,每一个核都有一个单独的mmu,电脑中的内存地址是虚拟地址,只是先分配一个虚拟地址,真实调用时才会去映射到真实的地址,这样cpu只有4g,所以也可以运行大于这个容量的程序。

    用户程序 -》 d -> 内存mu -》cache ->寄存器

    6.b 假设有4g,进程共享操作系统的内核,但是有自己的独立代码

    6.c 上下文切换

    1.进程之间的上下文切换(跨进程)

    2.进程内部用户和内核切换

    3.线程和线程之间的切换(进程内部跨线程)

    4.线程内部用户态和内核态切换

    • user o = new user();{

      ​ i = 0;对象头里面的i值不同,锁的状态不同

      }

    • synchronized(o)

自旋锁

  • 代码

    • pthread_spinlock_t a_lock

      pthread_spin_init(&a_lock);//初始化

      pthread_create t1

      pthread_create t2

      pthread_create t3

      pthread_spin_lock(&a_lock);//不会sleep,只会不断去获取锁

  • 描述锁

    • 自旋锁有两种层面
      • 操作系统,os自旋
      • 平台级别,reentrantLock.lock()(有个死循环一直tryAcquire()),
      • park就是sleep,
      • reentrantLock第一次拿锁失败,不会立即睡眠,不想立刻进入队列,不想睡眠,不想进入内核态,假设另一个线程释放了锁,所以再去拿锁,就可以拿到
      • java层面没有直接调用spinLock的代码,因为是操作系统的空转,性能低,它的原理是去模仿spin的空转
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值