java多线程整理(二)

一、线程调度方式
1、抢占式线程调度
每个线程由系统来分配执行时间,线程的切换不由线程本身决定;Java默认使用的线程调度方式是抢占式线程调度;我们可以通过Thread.yield()使当前正在执行的线程让出执行时间,但是,却没有办法使线程去获取执行时间;
2、协同式线程调度
每个线程的执行时间由线程本身来控制,线程执行完任务后主动通知系统,切换到另一个线程上;
两种线程调度方式的优缺点
协同式的优点:实现简单,可以通过对线程的切换控制避免线程安全问题;协同式的缺点:一旦当前线程出现问题,将有可能影响到其他线程的执行,最终可能导致系统崩溃;抢占式的优点:一个线程出现问题不会影响到其他线程的执行(线程的执行时间是由系统分配的,因此,系统可以将处理器执行时间分配给其他线程从而避免一个线程出现故障导致整个系统崩溃的现象发生);
二、线程安全的定义
简单来说,线程安全就是对于多个线程并发执行的操作不需要进行任何外部的控制,也不需要进行任何的协调,就能够保证程序的执行结果与开发人员的预期结果保持一致,那么这个多线程程序就是线程安全的;注意:线程安全问题一定是基于多个线程之间存在访问共享数据这一前提下的;
三、线程安全问题
一个自定义线程类,其中定义一个静态变量,然后启动两个线程对其进行count++操作,然后会发现比实际预期的会小。这就是因为线程并发安全问题。理解起来也容易,就是线程1获取到执行权累加后还没写回到堆内存中,线程2又获取到了执行权累加并写回堆内存,然后线程1再拿回去往堆内存赋值的时候实际上已经是++后的值了,又重复赋值了一遍相同的值而已。
四、synchronized解决、ReentrantLock、AtomicInteger
其实代码的写法不同synchronized关键字加的地方也不相同,如果说创建一个普通类,类里面有个count方法,然后你在main方法里面使用匿名内部类循环创建几个线程并调用,这种避免线程安全问题,直接简单地直接在方法上加一个关键字就可以解决线程并发问题。但是如果你的count方法同样是与前面一样抽离出来但是你写在了自定义实现的线程里面,这个就需要你在循环上加类锁才能避免高并发,方法属于线程类里面的只在count方法上加无法避免线程安全问题。ReentrantLock与synchronized一样可以处理线程安全问题。但是它需要自己lock后unlock。对于上面的count可以使用JDK5开始引入的原子性包操作函数,它的底层使用CAS+volatile规避掉了锁但是一样可以线程安全。synchronized同步块执行完成或者遇到异常是锁会自动释放,而lock必须调用unlock()方法释放锁,因此在finally块中释放锁**。
五、synchronized
synchronized关键字可以用在方法以及代码块上

synchronized的实现原理为:最大的特征就是在同一时刻只有一个线程能够获得对象的监视器(monitor),实现互斥行,释放锁的时候会将值刷新到主内存中,其他线程获取锁时会强制从主内存中获取最新的值。
synchronized是一种悲观锁,CAS是一种乐观锁。

参考:
https://www.cnblogs.com/wangwudi/p/12302668.html
 

 

 

 

 

 

 

 

 

参考博客:
https://blog.csdn.net/boker_han/article/details/79466524#comments_13635436

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值