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);
    }
  }
}

107.1

二、线程的同步(加锁)
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());
  }
}

107.2

修改一下代码,来解决上面的问题
我们只需要修改withdram方法即可

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

107.3
总结:加入线程同步机制,可以保证我们的数据是安全的,并且是准确,但是这也是牺牲性能为前提的。
三、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.欢迎关注微信公众号:傅里叶变换,个人公众号,仅用于学习交流,后台回复”礼包“,获取大数据学习资料
107.4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值