JavaSE02_Day01(中)-线程并发安全(线程同步、synchronized、同步块优化线程问题、静态线程同步)
一、线程并发安全
1.1 线程同步
讲解线程知识点的目的,其实是为了更好的使用CPU的资源,当多条线程并发对同一临界资源进行操作时,可能由于线程切换时机的不确定,导致程序在最终的执行过程中出现了错乱,或者程序瘫痪的情况。
假如多条线程共享类中的实例变量/静态变量,就可以称之为对同一临界资源进行操作。
临界资源:
临界资源是一次仅允许一个进程使用的共享资源。
各进程采取互斥的方式,实现共享的资源称作临界资源。
属于临界资源的硬件有,打印机,磁带机等;软件有消息队列,变量,数组,缓冲区等。
诸进程间采取互斥方式,实现对这种资源的共享。
临界区:
每个进程中访问临界资源的那段代码称为临界区(criticalsection),每次只允许一个进程进入临界区,进入后,不允许其他进程进入。
不论是硬件临界资源还是软件临界资源,多个进程必须互斥的对它进行访问。
多个进程涉及到同一个临界资源的的临界区称为相关临界区。
使用临界区时,一般不允许其运行时间过长,只要运行在临界区的线程还没有离开,其他所有进入此临界区的线程都会被挂起而进入等待状态,并在一定程度上影响程序的运行性能。
如果说需要解决刚刚上面所阐述的线程同步安全问题,需要将异步操作变成同步操作,可以有效的去解决"抢"资源的现象发生。
package cn.tedu.thread02;
/**
* 线程同步并发安全问题案例
* @author cjn
*
*/
public class ThreadBad {
public static void main(String[] args) {
BandCard bandCard = new BandCard();
//支付宝绑定银行卡付款
Thread thread1 = new Thread() {
测试结果:
支付宝:支付500元成功!!!
微信:支付500元成功!!!
微信0.0
支付宝-500.0
1.2 synchronized关键字
Java中提供了一个synchronized关键字,该关键字是同步锁,可以将某段代码变成同步操作,从而解决线程并发安全问题。
package cn.tedu.thread02;
/**
* 使用同步方法解决线程并发安全问题案例
* @author cjn
*
*/
public class SyncDemo01 {
public static void main(String[] args) {
Shop shop = new Shop();
Thread thread1 = new Thread() {
测试结果:
孟滕滕:正在挑选衣服......
孟滕滕:正在试衣服......
孟滕滕:离开试衣间,进行结账离开
苍老师:正在挑选衣服......
苍老师:正在试衣服......
苍老师:离开试衣间,进行结账离开
1.3 同步块优化线程同步问题
锁机制:Java中提供了一种内置的锁机制,也就是同步代码块,使用同步代码块,可以在确保线程并发安全的前提下,缩小同步范围,进而有效的进行解决同步方法所导致的性能慢的问题。
synchronized (同步监视器对象->锁对象){
//代码
}
锁对象:指代的是同一个锁对象的引用,通常我们会使用this(当前对象)关键字做为锁对象。
锁范围:使用同步代码块的时候,需要在可以解决同步安全问题的前提下,尽可能的去缩小同步范围,进而去提高整个程序软件的效率。
package cn.tedu.thread02;
public class SyncDemo02 {
public static void main(String[] args) {
Shop1 shop = new Shop1();
Thread thread1 = new Thread() {
测试结果:
孟滕滕:正在挑选衣服......
苍老师:正在挑选衣服......
苍老师:正在试衣服......
苍老师:离开试衣间,进行结账离开
孟滕滕:正在试衣服......
孟滕滕:离开试衣间,进行结账离开
如果测试的过程中,控制台显示苍老师试衣服和孟滕滕试衣服的输出语句挨着的情况,请注意查看,是苍老师试衣服离开试衣间的输出语句和孟滕滕正在试衣服的输出语句同时出现在控制台,这种情况是没有任何逻辑问题的,只不过是控制台打印的顺序问题。
1.4 静态线程同步
比如当前类中声明的方法是一个静态方法,我们仍然可以对静态方法进行加锁,静态方法也会具备同步功能,此时锁的对象就不再是类的对象,而是类对象,就是每个类都有的唯一的类对象,就是在JVM进行加载类的时候,会进行实例化Class实例用于表示这个类。Class的实例可以通过类名.class的方法进行获取。
类的对象与类对象:
(1)synchronized锁方法案例
package cn.tedu.thread02;
public class SyncDemo03 {
public static void main(String[] args) {
Thread thread1 = new Thread() {
测试结果:
苍老师:正在挑选衣服......
苍老师:正在试衣服......
苍老师:离开试衣间,进行结账离开
孟滕滕:正在挑选衣服......
孟滕滕:正在试衣服......
孟滕滕:离开试衣间,进行结账离开
(2)synchronized案例优化
package cn.tedu.thread02;
public class SyncDemo03 {
public static void main(String[] args) {
Thread thread1 = new Thread() {
苍老师:正在挑选衣服......
苍老师:正在试衣服......
苍老师:离开试衣间,进行结账离开
孟滕滕:正在挑选衣服......
孟滕滕:正在试衣服......
孟滕滕:离开试衣间,进行结账离开