多线程与高并发一:开启线程与synchronized

1:序言

关于多线程简单知识就不介绍了,从此篇开始介绍关于多线程的一些深入知识。这一篇主要介绍线程的开启和synchronized的一些使用。

2:线程开启的三种方式

a:T1 Extends Thread 重写run()方法
new T1().start();
b::T2 Implements Runnable 重写run()方法
new Thread(new T2()).start();
c:通过线程池来启动(严格来说也是上面的两种)

3:synchronized

asyncyronized锁住的不是方法而是对象(this/xxx.class),锁定方法和非锁定方法可以同时执行
bsynchronized(object),锁定对象一般用object,不要使用String常量和基本数据类型
csynchronized是可重入的,可以再次获取同一个对象的锁,计数加1.
d:synchronized是比较安全的,在加锁代码中如果发生了异常,会自动释放占有的锁,不会导致死锁
e一般使用了synchronized,就不需要volatile,synchronized保证原子性和一致性,而volatile只保证一致性,不保证原子性。所以volatile一般加在变量上(对于volatile这一篇不做重点介绍,以后会专门说明)。
f锁定某对象o,如果o的属性发生改变,不影响锁的使用;但是如果o变成另外一个对象,则锁定的对象发生改变。应该避免将锁定对象的引用变成另外的对象,给要加锁的对象加上final关键字
gsynchronized的底层实现,也叫锁的膨化
在很早之前的jdk中,synchronized是重量级的,它是直接对操作系统申请资源(内核态);
jdk1.5之后,jdk对synchronized进行了优化。
新创建的对象处于无锁状态,线程在访问synchronized标识的对象的时候,对象头部中markword有两个字节记录这个线程ID,记录是否加了锁,加了什么类型的锁。如果markword 中只有一个线程ID,说明不存在竞争,此时为偏向锁(用户态-)----->当有线程再次访问对象时,则markword 中会再次记录一个线程的ID,此时存在了线程争用,这两个个线程在自己的线程栈里面生成一个lr(lock record)锁纪录,然后以自旋的方式把自己的lr指针写到对象的makrkdown里,一旦一个写入,另外一个只能自旋等待,此时synchronized会升级为自旋锁,也叫轻量级锁,自旋锁占用cpu,但不访问操作系统,效率比较高(用户态),一般默认自旋10次-------->10次以后,自旋锁升级为重量级锁,直接访问操作系统,比较笨重(内核态)。
讨论
1:synchronized一旦升级后是不能降级的,所以可能导致一个问题:锁膨胀后,此时只有一个进程使用对象,显然再使用重量级锁会导致效率很慢,如果此时能降级成偏向锁就好了。但这个问题目前还没有解决。
2:什么时候使用自旋锁比较好?什么时候使用重量级锁?
执行时间短(加锁代码),线程数少,用自旋锁
执行时间长,线程数多,用系统锁
3:上面提到了内核态和用户态:这二代表两块内部内存,但访问用户态效率比较高,内核态是直接访问操作系统,而且内核态可以访问用户态,但用户态不能访问内核态。内核态能够访问所有的指令,而用户态只能访问用户能够访问的指令。像inter的cpu支持四种级别的分布:分成ring 0—ring3,linux内核工作在ring 0 级,能够访问所有的指令,linux用户工作在ring 3级,有些指令是不能访问的。

注意:本文仅代表菜鸟博主的个人观点,如果哪里不对或者路过技术大大有更好的想法,欢迎留言告知,分享和交流使我们进步,谢谢。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值