• Java连载107-join方法、锁(synchronized)机制以及原理


    一、join方法

    1.该方法为成员方法

    2.线程合并

    package com.bjpowernode.java_learning;
    
    ​
    
    public class D107_1_JoinMethod {
    
      public static void main(String[] args) throws InterruptedException{
    
        Thread t = new Thread (new Processer107());
    
        t.setName("t");
    
        t.start();
    
       
    
        //合并线程
    
        t.join();//t和主线程合并,可以理解为两个栈合并成一个栈了,也就是子线程与主线程合并成一个单线程了
    
       
    
        //主线程
    
        for(int i=0;i<5;i++) {
    
          System.out.println(Thread.currentThread().getName()+"-->"+i);
    
        }
    
      }
    
    }
    
    class Processer107 implements Runnable{
    
      public void run() {
    
        for(int i=0;i<5;i++) {
    
          try {
    
            Thread.sleep(1000);
    
          }catch(InterruptedException e) {
    
           
    
          }
    
          System.out.println(Thread.currentThread().getName()+"-->"+i);
    
        }
    
      }
    
    }

    二、线程的同步(加锁)

    1.异步编程模型:线程与线程之间,独立执行,谁也不等谁​。

    2.同步编程模型​:线程与线程之间,先执行一个,再执行另一个,有执行的先后顺序。

    3.​什么时候要同步?为什么​引入线程同步?

    (1)​为了数据安全,例如:银行取款​。但是为了​保证数据是安全的,必须加入线程同步机制;

    (2)​使用线程同步的情形:i.必须是​多线程环境;ii.多线程环境共享一个数据;iii.​共享的数据涉及到修改操作。

    以下程序演示取款例子(这个不使用同步的机制,看看会产生什么影响)

     
    
    package com.bjpowernode.java_learning;
    
    ​
    
    public class D107_2_SynchronizedMethod {
    
      public static void main(String[] args) throws InterruptedException{
    
        //创建一个公共账户
    
        Accout107_2 a = new Accout107_2("actno-001",8000.0);
    
        Processer107_2 c = new Processer107_2(a);
    
        //创建线程对同一个账户进行取款
    
        Thread t1 = new Thread(c);
    
        Thread t2 = new Thread(c);
    
        t1.start();
    
        t2.start();
    
       
    
      }
    
    }
    
    class Accout107_2 {
    
      private String actno;
    
      private double balance;
    
     
    
      public Accout107_2(String actno,double balance) {
    
        this.actno = actno;
    
        this.balance = balance;
    
      }
    
    ​
    
      public String getActno() {
    
        return actno;
    
      }
    
    ​
    
      public void setActno(String actno) {
    
        this.actno = actno;
    
      }
    
    ​
    
      public double getBalance() {
    
        return balance;
    
      }
    
    ​
    
      public void setBalance(double balance) {
    
        this.balance = balance;
    
      }
    
      //对外提供一个取款的方法
    
      public void withdraw(double money)  {
    
       
    
        double after = this.balance - money;
    
        try {
    
          //这里我们故意延迟了一下,可以看出余额不对了
    
          Thread.sleep(1000);
    
        }catch(InterruptedException e){
    
         
    
        }
    
        this.setBalance(after);
    
      }
    
    }
    
    class Processer107_2 implements Runnable{
    
      //账户
    
      Accout107_2 act;
    
      //Constructer
    
      public Processer107_2(Accout107_2 act) {
    
        this.act = act;
    
      }
    
      public void run() {
    
        act.withdraw(1000.0);
    
        System.out.println("取款成功,余额为:"+act.getBalance());
    
      }
    
    }

    修改一下代码,来解决上面的问题

    我们只需要修改withdram方法即可

     
    
      public void withdraw(double money)  {
    
       
    
        //把需要同步的代码,放到同步语句块中,参数一定要填共享对象
    
        synchronized(this) {
    
          double after = this.balance - money;
    
          try {
    
            //这里我们故意延迟了一下,可以看出余额不对了
    
            Thread.sleep(1000);
    
          }catch(InterruptedException e){
    
           
    
          }
    
          this.setBalance(after);
    
        }
    
      }

    ​总结:加入线程同步机制​,可以保证我们的数据是安全的,并且是准确,但是这也是牺牲性能为前提的。

    三、synchronized的原理

    t1线程和t2线程,t1线程执行到synchronized关键字,就会找this对象的对象锁,如果找到this对象锁,则进入到同步语句块中执行程序,当同步语句块中的代码执行结束汉字过后,t1线程​归还this的对象锁。

    在t1线程执行同步语句块的过程中,如果t2线程也过来执行以下代码,也遇到了synchronized关键字,所以也去找this的对象锁,但是该对象锁被t1线程持有,只能在这等待this对象锁​归还。​

    四、源码:

    D107_1_JoinMethod.java

    D107_2_SynchronizedMethod.java

    https://github.com/ruigege66/Java/blob/master/D107_1_JoinMethod.java

    https://github.com/ruigege66/Java/blob/master/D107_2_SynchronizedMethod.java

    2.CSDN:https://blog.csdn.net/weixin_44630050

    3.博客园:https://www.cnblogs.com/ruigege0000/

    4.欢迎关注微信公众号:傅里叶变换,个人公众号,仅用于学习交流,后台回复”礼包“,获取大数据学习资料

     

  • 相关阅读:
    GetUrlParam:获取Url参数,返回一个对象
    getPropByPath:根据字符串路径获取对象属性 : 'obj[0].count'
    dateFormater:格式化时间
    搜索引擎ElasticSearchV5.4.2系列二之ElasticSearchV5.4.2+kibanaV5.4.2+x-packV5.4.2安装
    大数据系列之并行计算引擎Spark部署及应用
    大数据系列之并行计算引擎Spark介绍
    大数据系列之数据仓库Hive安装
    大数据系列之数据仓库Hive命令使用及JDBC连接
    大数据系列之分布式计算批处理引擎MapReduce实践-排序
    大数据系列之Hadoop分布式集群部署
  • 原文地址:https://www.cnblogs.com/ruigege0000/p/12670712.html
Copyright © 2020-2023  润新知