线程安全与数据同步

  • 共享资源:指多线程同时对同一份资源进行访问(读写操作),被多个线程访问的资源就成为共享资源
  • 数据同步/资源同步:保证多个线程访问到的数据是一致的

数据同步示例

public class TicketWindowRunnable implements Runnable{
    private static final  int MAX = 500;
    private int index = 1;
    @Override
    public void run() {
        printIndex();
    }
    public  void printIndex(){
        while (index <= MAX){
            System.out.println("柜台" + Thread.currentThread() + "出票,票号" + index++);
    }

    /*
    * 除了 为共享资源添加static关键词,也可实现Runnable接口的方式,但是这两种情况下当Max的值从50增长到500、1000还是会出现超出最大值的情况
    * 因为共享资源依旧存在线程安全问题
    * */
    public static void main(String[] args) {
        TicketWindowRunnable test = new TicketWindowRunnable();

        Thread window1 = new Thread(test,"一号机");
        Thread window2 = new Thread(test,"二号机");
        Thread window3 = new Thread(test,"三号机");
        Thread window4 = new Thread(test,"四号机");

        window1.start();
        window2.start();
        window3.start();
        window4.start();
    }
}
  • 上述代码可能产生:
  • 1.某个号码被忽略:
    线程1和2执行到index = 65处,线程2将index增1后不打印,此时又由线程1完成答应此时输出为67,则66将会被忽略
    在这里插入图片描述
  • 2.某个号码重复出现
    在这里插入图片描述
  • 3.某个号码
    在这里插入图片描述
    注:上述图片借鉴《Java高并发编程详解》p59-p60

synchronized关键字

  • 出现共享资源线程同步问题时,可通过synchronized锁来解决,提供了一种排他机制,即同一时间只能有一个线程执行某些操作。
  • 官方含义:关键字实现了一个简单的策略来防止线程干扰和内存一致性错误,如果该线程对多个线程是可见的,那么对该对象的所有读或者写都将通过同步的方式来进行
  • 具体表现:
    a. 关键字提供了一种锁的机制,能够确保共享变量的互斥访问,从而防止不一致问题的出现
    b.(不懂)关键字包括monitor enter 和 monitor exit两个JVM指令,它能够保证在任何时候线程执行到monitor enter成功之前都必须要从主内存中获取数据,而不是从缓存中,在monitor exit运行成功之后,共享变量被更新后的值必须刷入主内存
    c.关键字的指令严格遵守java happens-before 规则,一个monitor exit指令之前必定要有一个monitor enter
  • 用法:不能用于对class以及变量进行修饰
    a.同步方法
    //[default|publilc|private|protected] synchronized [static] type method();
    public synchronized void sync(){
    ...
    }
    public synchronized static void staticSync(){
    ...
    ...
    } 
    
    b.同步代码块
    private finnal String NAME = "小北醒醒丶";
    public void sunc(){
    	synchronized (NAME){
    	...
    	}
    }
    
  • synchronized关键字提供了一种互斥机制,即同一时刻只能由一个线程访问同步共享资源

注意:

  • 1.与monitor关联的对象不能为空
//mutex为null,则每个对象和一个monitor关联,对象都为null,则monitor则无,所以mutex不能为null
private final Object mutex = null;
public void synacMethod(){
	synchronized(mutex){
	//
	}
}
  • 2.sunchronized作用域太大
    a.由于sunchronized关键字存在排他性,也就是说多有的线程必须串行经过sunchronized保护的共享区域,如果sunchronized作用域越大,则意味着效率越低。甚至失去并发的优势。
    b.sunchronized关键字应该尽可能只作用与共享资源(数据)的读写作用域
  • 3.不同的monitor企图锁相同的方法
    错误示例:
    public static class Task implements Runnable{
    	private final Obeject MUTEX = new Object();
    	@Override
    	public void run(){
    		//..
    		synchronized(MUTEX){
    		//..
    		}
    		//..
    	}
    }
    public static void main(String[] args){
    	for(int i = 0;i < 5;i++){
    		new Thread(Task::new).start();
    	}
    }
    
  • 上述代码中构造的五个线程的Runnable接口是五个实例,此时synchronized不能互斥与之对应的作用域。每一个线程争抢的monitor关联引用都是比起独立的,起不了互斥作用

多个锁的交叉导致死锁

  • 代码示例:
private final Object MUTEX_READ = new Object();
private final Object MUTEX_WRITE = new Object();
public void read(){
	sunchronized(MUTEX_READ ){
		sunchronized(MUTEX_WRITE ){
		//..
		}
	}
}

public void write(){
	sunchronized(MUTEX_WRITE ){
		sunchronized(MUTEX_WRITE ){
		//..
		}
	}
}
  • 注:sunchronized修饰同一个类的不同方法,争抢的是同一个monitor

引起死锁的原因

  • 交叉锁:
    线程A持有R1的锁等待获取R2的锁,线程B持有R2的锁等待获取R1的锁时,及哲学家吃面问题。
  • 内存不足:
    线程A与B需要内存30,线程A已占用10,线程B已占用20,剩余内存只存在20时,线程A与B都在等待彼此释放内存资源
  • 一问一答式的数据交换:
    客户端发送请求等待服务器响应,服务器由于某种原因没有收到请求,服务器等待客户端请求,此时都在等待,所以导致死锁
  • 数据库锁:
    某个线程执行for update语句退出了事务,其他线程访问该数据库时都将陷入死锁
  • 文件锁:
    某个线程获得了文件锁意外退出,其他读取该文件的线程也将会进入死锁直到系统释放文件句柄资源:
  • 死循环引起的死锁:
    由于编码原因,进入死循环,CPU占用率居高不下,一般称为系统假死
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随与博主沟通,博主会及解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随与博主沟通,博主会及解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随与博主沟通,博主会及解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随与博主沟通,博主会及解答。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值