• 多线程详细解析(二) 线程的共享互斥与线程的协调


    线程的共享互斥

    在多线程程序里,多个线程可以自由操作,当然就有可能同时操作同一实例,这种情况有时会造成不必要的问题。

    假设现在要在银行取钱,确认可用余额这部分的代码应为:

    if(可用余额大于等于欲提领金额){

    从可用余额中减去提领金额。

    }

    但是,若让两个线程同时执行,可用余额可能变成负数。

    假设,账户中共有1000元,现在有A和B两个线程,都要取1000元。

    当线程A和B同时操作,由于时间差,可能发生线程B夹在线程A中进行操作。

    当A判断可用余额大于等于欲提领金额是,返回为TRUE,但是却并未进行提领金额,这是线程B又进行判断,仍然为TRUE。

    于是线程A和线程B都从余额中扣除1000元。那么余额就变成-1000元。

    这个时候就需要一种机制来防止这种问题,当一个线程在操作一个实例时,不允许其他线程同时操作这一实例。

    这种机制就叫做共享互斥


    在JAVA中,处理线程的共享互斥时,会用到一个关键字synchronized.


    当一个方法加上synchronized是,这个方法一次只能让一个线程执行。这种方法称为同步方法。

    现在利用synchronized关键字来解决上面问题:

    	private int money;
    	private String name;
    	
    	public Bank(int money, String name) {
    		super();
    		this.money = money;
    		this.name = name;
    	}
    
    
    	//存款
    	public synchronized void deposit(int m){
    		money+=m;
    	}
    	
    	
    	//取款
    	public synchronized String withdraw(int m){
    		if(money>=m){
    			return "取款成功";
    		}else{
    			return "取款失败,余额不足";
    		}
    	}
    

    一个线程执行deposit()方法时,那么其他线程就不能同时执行同一实体的deposit()和withdraw()方法。


    线程的协调:

    假设我们想更近一步,不止是有线程在执行,其他线程就乖乖等待的简单型而已,例如:

    1、若该空间有空闲则写入数据,若非空闲则等候知道出现空闲为止。

    2、当该空间已空出,则通知正在等候的线程。

    这是根据空间是否有空闲来进行判断的线程处理。在Java中有wait,notify和notifyall三个方法来进行处理

    wait:是让线程乖乖等待的方法。obj.wait();

    notify、notifyAll:唤醒等候中的线程的方法。obj.notify();obj.notifyAll();

     在调用上述三个方法是,该线程必须握有欲调用线程的锁,才可以执行,否则会抛出异常。

    补充说明:

    notify()和notifuAll()到底使用哪一个:

    notify()方法中,当正在等候的线程不止一个,规格并未说明到底调用唤醒哪一个线程,是第一个?最后一个?还是随机?

    都是根据系统而定的,因此,在写程序是,程序属性最好不要写成会根据线程而有所变动。

    选择notify()方法,唤醒的线程数量比较少,程序处理速度要比notifuAll()快。但是选择notify()时,若这部分处理的不好,可能会有挂掉的风险,一般来说,选择notifuAll()写出的程序代码会比notify()可靠。

    除非你能确定程序员对代码的的意义和能力限度一清二楚。否则还是使用notifuAll()比较好。


  • 相关阅读:
    ffmpeg full help
    docker 服务命令
    php 查看swoole版本
    vue/cli 的启动
    TP框架的使用,不需要阿帕奇
    mysql 的文件恢复
    mac下使用iterm实现自动登陆
    跨库怎样查询
    swoole和websocket的关系
    mac上mysql的安装和使用
  • 原文地址:https://www.cnblogs.com/xsyfl/p/6842524.html
Copyright © 2020-2023  润新知