6.11Java多线程、并发、同步、synchronized块

6.11Java多线程、并发、同步、synchronized块

synchronized块

  • 同步块:synchronized(object){},object称为同步监视器

    • object可以是任何对象,但是推荐使用共享资源作为同步监视器

    • 同步方法中无需指定同步监视器(因为监视对象是this对象本身或者class类的模子)

  • 同步监视器的执行过程

    • 第一个线程访问,锁定同步监视器,执行代码

    • 第二个线程访问,同步监视器被锁定,无法访问

    • 第一个线程访问完毕,解锁同步监视器

    • 第二个线程访问,发现同步监视器未锁,锁定并访问

synchronized块可以锁定具体的一个对象

Java当中的四种块

  • 方法当中的块--->局部块

    • 解决变量的作用域--->快速释放内存

  • 类中的块(方法外)--->构造块

    • 初始化对象信息--->对象的信息

  • 静态块(static)

    • 只加载一次

    • 初始化类

    • 先于构造块执行--->类的信息

  • 同步块--->在方法中,解决线程安全的问题--->加一个synchronized、监视对象

    • 推荐使用共享资源作为同步监视器--->只有共享的资源才可能会被多线程访问

四种块

使用synchronized同步对象锁,锁定方法保证线程安全
package iostudy.synchro;

public class SynBlockTestNo1 {
   public static void main(String[] args) {

       /*资源类对象*/
       AccountTest accountTest = new AccountTest(100, "Money");

       /*线程对象*/
       SynDrawing you = new SynDrawing(accountTest, 80, "JunkingBoy");
       SynDrawing she = new SynDrawing(accountTest, 90, "Lucifer");
       you.start();
       she.start();

  }
}

/**
* 模拟提款机提款类--->多线程
* @since JDK 1.8
* @date 2021/6/10
* @author Lucifer
*/
class SynDrawing extends Thread{

   /*创建实现类对象--->面向对象的思想*/
   AccountTest accountTest; //取出的账户
   int drawingMoney; //取出的钱数
   int pocketTotal; //取出的钱的总数

   /*创建构造器,将属性定义为参数*/
   public SynDrawing(AccountTest accountTest, int drawingMoney, String name) {
       super(name); //线程的名称
       this.accountTest = accountTest;
       this.drawingMoney = drawingMoney;
  }

   /*重写run方法--->线程的具体实现*/
   @Override
   public void run() {
       test();
  }

   /*
   使用同步块锁定线程
    */
   public void test(){

       /*如果金额为0,结束方法*/
       if (accountTest.money<=0){
           return;
      }

       /*使用同步块锁定线程*/
       synchronized (accountTest){

           /*在存钱和取钱的时候加入条件*/
           if (accountTest.money-drawingMoney<0){
               /*结束方法*/
               return;
          }

           /*模拟取款的网络延迟*/
           try {
               Thread.sleep(1000);
          }catch (InterruptedException e){
               System.out.println(e.getMessage());
               e.printStackTrace();
          }
       /*
       理论上说加了判断就会控制结果
       但是实际上不会,这个需要对资源+锁实现控制的效果
        */

           /*账户的金额-取出的金额*/
           accountTest.money -= drawingMoney;
           /*口袋中的金额+取出的钱*/
           pocketTotal += drawingMoney;

           /*因为继承了父类所以可以直接用this--->获取线程的名称*/
           System.out.println(this.getName() + "--->账户余额为:" + accountTest.money);
           System.out.println(this.getName() + "--->身上余额为:" + pocketTotal);

      }
  }
   /*
   假设账户没有金额了,其他进来访问还是需要等待
   所以在等待之前加入一个判断
   这样可以提高并发量--->性能就是从小细节当中调优的
    */
}
demo2--->容器中添加同步锁(synchronized)
package iostudy.synchro;

import java.util.ArrayList;
import java.util.List;

/**
* 操作容器:
* 1、这里面没有方法,要思考锁的对象
* 2、保证安全要思考锁定的范围
* @since JDK 1.8
* @date 2021/6/11
* @author Lucifer
*/
public class SynBlockTestNo2 {
   public static void main(String[] args) throws InterruptedException{

       /*创建容器*/
       List<String> list = new ArrayList<String>();
       /*循环添加一万个线程*/
       for (int i=0; i<10000; i++){
           new Thread(() -> {

               /*加一个对象锁,保证线程的准确性*/
               //同步块,保证线程安全
               synchronized(list){
                   list.add(Thread.currentThread().getName());
              }
          }).start();
      }

       /*线程等待*/
       Thread.sleep(10000);
       System.out.println(list.size());

  }
}

 

posted @ 2021-06-12 12:57  俊king  阅读(64)  评论(0编辑  收藏  举报