• 多线程--基础篇2--同步


    在两个线程共卖100张票的时候,也会出现问题,同时卖同一张票。

    程序如下:

    public class TestThread implements Runnable{
             private int j=100;
             public void run(){
                   for(int i = 0 ;i<100;i++){
                        if(j>0){
                             try {
                                  Thread.sleep(300);//注意这里休眠了300毫秒
                             } catch (InterruptedException e) {
                                   e.printStackTrace();
                             }
                             System.out.println("卖第"+j+"张票!");
                              j--;   
                        }
                     }
                 }
    }

     public static void main(String[] args) {
              TestThread m=new TestThread();
              new Thread(m).start();
              new Thread(m).start();
     }

    结果:

    卖第100张票!
    卖第100张票!
    卖第98张票!
    卖第98张票!

    ......

    造成此问题的根本原因在于,判断剩余票数和修改票数之间加入了延迟操作。

    如果想解决这样一个问题,就必须使用同步,所谓的同步就是指多个操作在同一时间段内只能有一个线程进行,其他线程要等待此线程完成之后才可以继续执行。

    在Java中可以通过同步代码的方法进行代码的加锁操作,同步的实现由两种方式:同步代码块和同步方法

    1. 同步代码块:使用synchronized关键字进行同步代码块的声明,但是在使用此操作时必须明确的指出到底要锁定的是哪个对象,一般都是以当前对象为主:

    synchronized(对象){//一般都是将this进行锁定

        需要同步的代码;

    }

    使用同步代码块修改之前的程序:

    public class TestThread implements Runnable{
         private int j=100;
         public void run(){
              for(int i = 0 ;i<100;i++){
                   synchronized (this) {//同步代码块,要将if判断条件包括在其中,否则会出现卖出第0张票的问题
                      if(j>0){
                          try {
                               Thread.sleep(300);
                          } catch (InterruptedException e) {
                                e.printStackTrace();
                          }
                          System.out.println("卖第"+j+"张票!");
                          j--; 
                      }
                 }
             }
        }
    }

    2. 同步方法:将要同步的代码块抽取成方法

    public class TestThread implements Runnable {
         private int j = 100;

         public void run() {
              for (int i = 0; i < 100; i++) {
                   sale();
              }
         }
         public synchronized void sale() {//同步方法
             if (j > 0) {
               try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("卖第" + j + "张票!");
                j--;
            }
         }
    }

  • 相关阅读:
    rabbitMq交换机direct、topics
    rabbitMq及安装、fanout交换机-分发(发布/订阅)
    rabbitmq
    .sh文件启动 jenkins
    雪花算法、二进制运算
    收银台数据库存储AES加解密
    数据库事物
    excel技巧
    日期计算、正则、sequence、索引、表连接、mybatis
    oracle常用函数介绍
  • 原文地址:https://www.cnblogs.com/james1207/p/3281309.html
Copyright © 2020-2023  润新知